LOJ#2863. 「IOI2018」组合动作 交互
比较友好的一道交互题.
想出来还是蛮开心的.
对于第一个位置先猜 $A$ 和 $B$,然后有一个合法的话猜 $A$,否则去猜 $X$,$Y$ 其中的一个.
由于题目保证首次出现的数不会在中间再次出现,所以中间的数只有 3 种情况.
如果还是用猜首位的策略去猜中间的数的话可以在 $2n$ 次询问解决该问题,但是这并没有用到首字母不在中间出现这个性质.
考虑到每次允许猜测长度为 $0$ ~ $4n$,不妨从 $4n$ 上去考虑.
显然 4=3+1,那么我们发现每次可以对一个字母的所有后继都猜一遍.
比如 $ans+AB+ans+AX+ans+AA$.
除此之位我们还可以猜另外的一个字母 $y$.
于是,返回值就有 3 种可能:press=1:说明是 $y$,press=2,是出现 3 次的那个,press=0 是没有出现的.
这样,中间的字母就可以靠 1 次询问来确定了.
code:
#include <bits/stdc++.h>
#include "combo.h"
using namespace std;
string p,ans;
string guess_sequence(int N) {
int x,y,z,c,n=N;
c=press("AABB");
if(!c) {
z=press("X");
if(z) ans+="X";
else ans+="Y";
}
else {
z=press("A");
if(z) ans+="A";
else ans+="B";
}
if(N==1) return ans;
for(int i=2;i<n;++i) {
if(ans[0]=='A') {
// no A
p=ans+"BX"+ans+"BY"+ans+"X"+ans+"BB";
z=press(p);
if(z==i-1) ans+="Y";
if(z==i) ans+="X";
if(z==i+1) ans+="B";
}
if(ans[0]=='B') {
p=ans+"AX"+ans+"AY"+ans+"X"+ans+"AA";
z=press(p);
if(z==i-1) ans+="Y";
if(z==i) ans+="X";
if(z==i+1) ans+="A";
}
if(ans[0]=='X') {
p=ans+"BB"+ans+"BY"+ans+"Y"+ans+"BA";
z=press(p);
if(z==i-1) ans+="A";
if(z==i) ans+="Y";
if(z==i+1) ans+="B";
}
if(ans[0]=='Y') {
p=ans+"BX"+ans+"BB"+ans+"X"+ans+"BA";
z=press(p);
if(z==i-1) ans+="A";
if(z==i) ans+="X";
if(z==i+1) ans+="B";
}
}
string s;
s.clear();
s+=ans[0];
c=press(ans+"A"+s+ans+"B");
if(c!=n) {
z=press(ans+"X");
if(z==n) ans+="X";
else ans+="Y";
}
else {
z=press(ans+"A");
if(z==n) ans+="A";
else ans+="B";
}
return ans;
}

浙公网安备 33010602011771号