Rudolph and Mimic

Codeforces Round 883 (Div. 3)
F. Rudolph and Mimic
题目链接

题意:

这是一项interactive task(交互题)。

鲁道夫是一位研究外星生物的科学家。鲁道夫面前有一个房间,房间里散落着 n n n 种不同的物体。在这些物体中,有一个神奇的生物——模仿者,它可以变成任何物体。他已经在这个房间里伪装好了,鲁道夫需要通过实验找到他。

实验分几个阶段进行。每个阶段都会发生以下情况:

  • 鲁道夫查看房间里的所有物品,并写下它们的类型。每个物体的类型都用数字表示;同一类型的物体可能有好几个。
  • 检查完毕后,鲁道夫可以指出一个他认为是模仿品的物体。之后,实验就结束了。鲁道夫只有一次尝试的机会,所以如果他不确定模仿者的位置,就会进行下一步。
  • 鲁道夫可以从房间里拿走任意数量的物品(可能是零)。然后,鲁道夫离开房间,此时所有的物体,包括拟态物体,会相互混合,它们的顺序也会改变,拟态物体可以变成任何其他物体(即使是房间里没有的物体)。
  • 之后,鲁道夫回到房间,重复这个阶段。模仿者可以不改变外观,但不能连续两个阶段以上保持同一个物体。

鲁道夫的任务是在不超过五个阶段内探测到模仿者。

输入:

第一行包含一个整数 t t t ( 1 ≤ t ≤ 1000 ) (1 \le t \le 1000) (1t1000) - 测试用例数。 ( 1 ≤ t ≤ 1000 ) (1 \le t \le 1000) (1t1000) - 测试用例的数量。

每个测试用例的第一行包含一个整数 n n n ( 2 ≤ n ≤ 200 ) (2 \le n \le 200) (2n200) - 房间中的物体数量。 ( 2 ≤ n ≤ 200 ) (2 \le n \le 200) (2n200) - 房间中对象的数量。

每个测试用例的第二行包含 n n n 个整数 a 1 a_1 a1 , a 2 a_2 a2 ,…, a n a_n an ( 1 ≤ a i ≤ 9 ) (1 \le a_i \le 9) (1ai9) -对象类型。

交互:

阅读完输入数据集的说明后,您必须进行不超过 5 5 5次查询。阅读输入数据被视为第一阶段的开始,模仿器可能已经开始变化。

请求是一行。行的第一个字符表示请求类型。要删除对象,请打印"-"。然后打印数字 k k k --要删除多少个对象。然后是 k k k 个数字–对象在当前位置的索引。索引从 1 开始。您可以删除模仿对象,但在这种情况下,您将无法指向它,并将得到 "错误答案 "的判决。

作为对请求的回应,您将收到一行包含整数的信息–移除和混合后房间中剩余的物品。

要指明模仿对象的位置,请打印"!",然后打印模仿对象的索引。

如果正确指定了模仿器的位置,任务将被视为已完成。

思路:

其实刨去交互标签,这个题的思路还是蛮简单的,虽然物品的顺序会变,但是除了模仿者以外的物品一定不会改变类型,也就是每种类型的个数一定是不变的。如果模仿者要变成其他类型的物品,那么变成的类型一定会凭空多出一个来。那么其他类型的物品就都可以删掉了。

因为上面说了模仿者不会两个回合以上维持同一个类型,因此至多两个回合就会有一种类型的物品凭空多一个,那么我们就只留下这种类型的物品,随后再至多两回合,模仿者会变成其他类型的物品来送死,这时候凭空出现的那个就是模仿者。

具体来说,存储一下出房间之前每种类型个数,然后回来读取物品。如果有某种类型数量比离开前多1,而且这个类型就一个,那么它就是模仿者,否则把其他类型都删掉。如果找到了模仿者就退出循环,否则把这些类型当成下一轮离开房间时的类型个数,如此循环。

它说了,你可以删掉模仿对象,但是这会导致你永远不可能找到模仿对象了,所以最后一定会WA。所以一开始的时候没有把握就不碰,它给的这些样例纯纯脑瘫。


关于缓冲区,参考1参考2

难的是交互部分,一个不小心就是ILE。我的建议是每行结尾用cout输出endl来换行。交互题是两个程序通过标准输出输出进行对话,而标准输入输出stdinstdout都是行缓冲OI,所以每一行输出结束后都要清空缓冲区

程序标准输入输出存在一个缓冲区(可以理解为输入时窗口中光标所在的那一行),你可以对缓冲区内的内容进行编辑,它暂时不会将缓冲区的内容给程序输入,因此要决定输入的时候我们会用换行把数据输入,这个操作就会引起 清空缓冲区,每次缓冲区清空时程序才进行读入。

然后呢,你的程序看似输出了内容,但是由于没有清空缓冲区,实际上并没有给题目程序输入(所以有的评测平台会给TLE判决),这个fflush(stdout) 或 C++ 中的 cout.flush() 完成的工作就是清空缓冲区,将缓冲区的内容给题目程序进行输入,endl在换行的同时也会清空缓冲区。输出’\n’也可以,不过不如endl和flush保险。

实际上我们在屏幕上看到的程序输出也是行缓冲,本来不应该在输出换行前进行输出的,但是被某些配置或者优化给提前刷新了。

code:

#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;

int T,n;
vector<int> a(10),t(10);
vector<vector<int> > item(10,vector<int>(200));

int main(){
	cin>>T;
	while(T--){
		cin>>n;
		for(int i=1;i<=9;i++)
			a[i]=0;
		for(int i=1,tmp;i<=n;i++){
			cin>>tmp;
			a[tmp]++;
		}
		a[0]=n;
		cout<<"- 0"<<endl;
		while(true){
			for(int i=0;i<=9;i++)
				t[i]=item[i][0]=0;
			for(int i=1,tmp;i<=a[0];i++){
				cin>>tmp;
				item[tmp][++item[tmp][0]]=i;//item[tmp][0]存储这tmp类型的物品的个数
				t[tmp]++;
			}
			int f=0;
			for(int i=1;i<=9;i++){
				if(a[i]<t[i])f=i;
			}
			if(f==0){
				t[0]=a[0];
				a=t;
				cout<<"- 0"<<endl;
				continue;
			}
			else if(t[f]==1){
				cout<<"! "<<item[f][1]<<endl;
				break;
			}
			
			t[0]=t[f];
			cout<<"- "<<a[0]-t[0];
			for(int i=1;i<=9;i++)
				if(i!=f){
					for(int j=1;j<=item[i][0];j++)
						cout<<" "<<item[i][j];
					t[i]=0;//删掉 
				}
			a=t;
			cout<<endl;
		}
	}
	return 0;
} 
  • 30
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值