#交互,分类讨论#CF1292E Rin and The Unknown Flower

题目传送门


分析

先尝试锁定一个字母,显然询问 CH,CO,CC 会比直接询问 C 更优,虽然牺牲了最后一个位置是否为 C 的查询。

同理,询问 HH,OH,CH 会比直接询问 H 更优,虽然牺牲了第一个位置是否为 H 的查询。

可以发现这样询问非首尾位置未填的一定是 OCH 一定会被询问出来。

然后首字母只可能填 O,H,尾字母只可能填 C,O,然后再三次判断就可以知道整个串(如果三次判断都不知道,那只能是最后一种情况)

那么操作代价就是 54+41n2,可以发现在 n>4 时都不超过 75n=5 时最小,为 1.37

那么只剩下 n=4 的情况,显然直接这样问肯定会代价过高。

可以发现只要确定其中两个位置,就可以花不超过 9116 的代价确定其它位置,

还是尝试锁定 C 字母,如果锁定得了那么只需要花 34 的代价,

同时其它位置就可以花不超过 6116 的代价,合起来就是 1716

如果 C 字母不能锁定,再询问 OH,同理,只需要花 44+6116=2116 的代价。

再询问 HH,如果 H 被锁定,其实第一二位一定是 H,如果不是那么它在之前一定会被询问出来。

如果第三四位没有被询问出来,那么第三位一定是 O,否则第三位一定被询问出来,

同理只需要确定尾位,需要 54+116=2116

最后一种情况,中间两位一定是 O,最后询问 OOO,通过 54+19=4936 就可以确定所有位置啦


代码

#include <iostream>
using namespace std;
const char ch[3]={'H','O','C'};
int k,x,Test,n,AC; char S[51];
void doit(char ch,char Ch){
	cout<<"? "<<ch<<Ch<<endl;
	cin>>k;
	for (int i=0;i<k;++i)
		cin>>x,S[x]=ch,S[x+1]=Ch;
}
void answ(int t){
	bool flag=1;
	if (S[1]=='\0'&&S[n]=='\0'){
		for (int o=2;o>=t&&flag;--o)
		for (int j=0;j<2&&flag;++j)
		if (!t||o!=1||j!=1){
			S[1]=ch[j],S[n]=ch[o],cout<<"? ";
			for (int i=1;i<=n;++i) cout<<S[i]; cout<<endl;
			cin>>k;
			if (k) cin>>x,flag=0;
		}
		if (flag) S[1]=S[n]='O',flag=0;
	}
	for (int i=1;i<n&&flag;++i)
	if (S[i]=='\0'&&S[i+1]=='\0'){
		for (int o=0;o<3&&flag;++o)
		if (!t||o<2||i==n-1)
		for (int j=0;j<2&&flag;++j){
			S[i]=ch[j],S[i+1]=ch[o],cout<<"? ";
			for (int i=1;i<=n;++i) cout<<S[i]; cout<<endl;
			cin>>k;
			if (k) cin>>x,flag=0;
		}
		flag=0; break;
	}
	if (flag){
		for (int i=1;i<=n;++i)
		if (S[i]=='\0'){
			for (int o=0;o<3&&flag;++o) if (!t||o<2||i==n){
				S[i]=ch[o],cout<<"? ";
				for (int i=1;i<=n;++i) cout<<S[i]; cout<<endl;
				cin>>k;
				if (k) cin>>x,flag=0;
			}
		}
	}
	cout<<"! ";
	for (int i=1;i<=n;++i) cout<<S[i];
	cout<<endl;
}
int main(){
	ios::sync_with_stdio(0);
	for (cin>>Test;Test;--Test){
		cin>>n;
		if (n>4){
			for (int i=0;i<3;++i) doit('C',ch[i]);
			doit('H','H'),doit('O','H'); 
			for (int i=2;i<n;++i) if (S[i]=='\0') S[i]='O';
			answ(1);
		}else{
			for (int i=0;i<3;++i) doit('C',ch[i]);
			if (S[2]!='\0'||S[3]!='\0') answ(0);
			else{
				doit('O','H');
				if (S[2]!='\0'||S[3]!='\0') answ(0);
				else{
					doit('H','H');
					if (S[2]!='\0'){
						if (S[4]=='\0'){
							if (S[3]=='\0') S[3]='O';
							cout<<"? ";
							for (int i=1;i<4;++i) cout<<S[i];
							cout<<'C'<<endl;
							cin>>k;
							if (k) cin>>x,S[4]='C';
							    else S[4]='O';
						}
						cout<<"! ";
						for (int i=1;i<=4;++i) cout<<S[i];
						cout<<endl;
					}else{
						S[2]=S[3]='O';
						cout<<"? OOO"<<endl;
						cin>>k;
						if (k==2) cin>>x,cin>>x,S[1]=S[4]='O';
						else if (k==1){
							cin>>x,S[x]=S[x+2]='O';
							if (S[1]=='\0') S[1]='H';
							    else S[4]='C';
						}else S[1]='H',S[4]='C';
						cout<<"! ";
						for (int i=1;i<=4;++i) cout<<S[i];
						cout<<endl;
					}
				}
			}
		}
		for (int i=1;i<=n;++i) S[i]='\0';
		cin>>AC;
	}
	return 0;
} 
posted @   lemondinosaur  阅读(36)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示