1 条题解

  • 0
    @ 2025-8-24 23:04:34

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar Zskioaert1106
    值得一提的是,我在四个洛谷有 Remote Judge 的国外 OJ 上的账号都不是我的洛谷用户名。

    搬运于2025-08-24 23:04:34,当前版本为作者最后更新于2024-10-01 21:57:16,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    题目传送门:P11138 [APC001] C - Not APC

    题意简述

    消消乐。如果能找到按顺序的 APC 串就消掉,要让字符串尽量小并输出过程。

    题目分析

    像这道题一样用字符串队列的题经有很多了,本题不过是要输出过程。

    我们建三个队列来存字符 APC 的数量和位置,遍历一遍字符串。当我们看到字符 A时,肯定要存入队列以备后面的 PC;当我们看到 P 时,如果加上它后存 P 的队列数量小于等于存 A 的队列,那这些字符都能匹配到 A;如果是 C 则要当存 AP 的队列都比它大,才考虑将它入队。

    一旦存 C 的队列有值(此时另外两个队列一定也有),则为了利益最大就正好从队列最前端的 AP 选字符,将这三个消掉并将这次的操作存入另一个队列。

    此时将这三个消掉的字符在字符串中的位置要替换成一个不存在的以便之后输出。

    输出时先遍历一遍字符串,如果不是之前的专用替换字符就输出,之后输出存操作的队列的长度,然后次序输出。

    ……枯燥的文字好抽象啊,还是上代码吧。

    编写代码

    首先初始化各种队列,为了方便定义一个三元组结构体类型的队列存操作:

    #include<iostream>
    #include<queue>
    using namespace std;
    int t;
    string s;
    queue<int>qa,qb,qc;
    struct three{
    	int a,b,c;
    };
    queue<three>q;
    

    然后编写字符串处理部分:

    for(int i=0;i<s.size();i++){
      if(s[i]=='A')qa.push(i+1);
      else if(s[i]=='P'&&(qa.size()>qb.size()))qb.push(i+1);
      else if(s[i]=='C'&&(qb.size()>qc.size())){
        qc.push(i+1);
        three o;o.a=qa.front(),o.b=qb.front(),o.c=qc.front();
        s[o.a-1]=char(0),s[o.b-1]=char(0),s[o.c-1]=char(0);
        qa.pop(),qb.pop(),qc.pop();
        q.push(o);
      }
    }
    

    当字符为能用到的 C 时,(放存它的队列只是为了清晰明了)首先把三元组存起来入队,然后把入队的三个字符出队,再占位删除字符串中的相应位置。

    • 注意,操作输出时下标从 11 开始,但字符串的下标从 00 开始。

    然后是输出部分:

    bool b=1;
    for(int i=0;i<s.size();i++){
      if(s[i]!=char(0)){
        cout<<s[i];
        b=0;
      }
    }
    if(b)cout<<"Perfect";
    cout<<'\n'<<q.size()<<'\n';
    while(!q.empty()){
      cout<<q.front().a<<' '<<q.front().b<<' '<<q.front().c<<'\n';
      q.pop();
    }
    

    每次操作边输出边出队即可。注意:

    • 每个测试数据输出后要清空四个队列。

    • 记得特判字符串为空输出 Perfect

    知周所众,多测函数好。所以这是我的主函数(起名废默默碎了):

    int main(){
    	cin>>t;
    	while(t--){
    		cin>>s;
    		doing();
    		while(!qa.empty())qa.pop();
    		while(!qb.empty())qb.pop();
    		while(!qc.empty())qc.pop();
    	}
    	return 0;
    }
    

    这题除了难点外还是蛮简单的,下面放完整代码:

    完整代码

    (赛时)

    #include<iostream>
    #include<queue>
    #define doing doing()
    using namespace std;
    int t;
    string s;
    queue<int>qa,qb,qc;
    struct three{int a,b,c;};
    queue<three>q;
    void doing{
    	for(int i=0;i<s.size();i++){
    		if(s[i]=='A')qa.push(i+1);
    		else if(s[i]=='P'&&(qa.size()>qb.size()))qb.push(i+1);
    		else if(s[i]=='C'&&(qb.size()>qc.size())){
    			qc.push(i+1);
    			three o;o.a=qa.front(),o.b=qb.front(),o.c=qc.front();
    			s[o.a-1]=char(0),s[o.b-1]=char(0),s[o.c-1]=char(0);
    			qa.pop(),qb.pop(),qc.pop();
    			q.push(o);
    		}
    	}
    	bool b=1;
    	for(int i=0;i<s.size();i++){
    		if(s[i]!=char(0)){
    			cout<<s[i];
    			b=0;
    		}
    	}
    	if(b)cout<<"Perfect";
    	cout<<'\n'<<q.size()<<'\n';
    	while(!q.empty()){
    		cout<<q.front().a<<' '<<q.front().b<<' '<<q.front().c<<'\n';
    		q.pop();
    	}
    	return ;
    }
    int main(){
    	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    	cin>>t;
    	while(t--){
    		cin>>s;
    		doing;
    		while(!qa.empty())qa.pop();
    		while(!qb.empty())qb.pop();
    		while(!qc.empty())qc.pop();
    	}
    	return 0;
    }
    

    赛时 AC。当然我们可以把没必要的队列简化掉:

    #include<iostream>
    #include<queue>
    using namespace std;
    queue<int>qa,qp;
    struct three{
    	int a,b,c;
    };
    queue<three>q;
    void doing(string s){
    	for(int i=0;i<s.size();i++){
    		if(s[i]=='A')qa.push(i+1);
    		else if(s[i]=='P'&&(qa.size()>qp.size()))qp.push(i+1);
    		else if(s[i]=='C'&&(!qp.empty())){
    			three o;o.a=qa.front(),o.b=qp.front(),o.c=i+1;
    			s[o.a-1]=char(0),s[o.b-1]=char(0),s[i]=char(0);
    			qa.pop(),qp.pop(),q.push(o);
    		}
    	}
    	bool b=1;
    	for(int i=0;i<s.size();i++){
    		if(s[i]!=char(0)){
    			cout<<s[i];
    			b=0;
    		}
    	}
    	if(b)cout<<"Perfect";
    	cout<<'\n'<<q.size()<<'\n';
    	while(!q.empty()){
    		cout<<q.front().a<<' '<<q.front().b<<' '<<q.front().c<<'\n';
    		q.pop();
    	}
    }
    int main(){
    	int t;
    	cin>>t;
    	while(t--){
    		string s;
    		cin>>s;
    		doing(s);
    		while(!qa.empty())qa.pop();
    		while(!qp.empty())qp.pop();
    	}
    	return 0;
    }
    

    AC 记录

    • 1

    信息

    ID
    9433
    时间
    1000ms
    内存
    500MiB
    难度
    3
    标签
    递交数
    0
    已通过
    0
    上传者