qoj12310 The Good, the Bad and the Ugly
题意
懒得总结了,直接放原文。
考虑一个数轴。一个玩家初始位于位置 \(x = p\)。在每轮开始时,你可以说“+”或“-”。之后,玩家根据你所说的内容改变位置。具体来说,如果你说 \(t\) 而玩家位于位置 \(x\),那么他将移动到位置 \(x' = x + d_t\),其中 \(d_+\) 和 \(d_-\) 是两个整数常数。
你不知道具体的值 \(p\)、\(d_+\) 和 \(d_-\),但你知道玩家是好人、坏人或丑人(发挥你的想象力):
- 好人玩家:\(p = m\),\(d_+ = 2\),\(d_- = -1\);
- 坏人玩家:\(p = -m\),\(d_+ = 1\),\(d_- = -2\);
- 丑人玩家:要么 \(p = m\) 要么 \(p = -m\),并且要么 \(d_+ = 1\) 和 \(d_- = -1\),要么 \(d_+ = -1\) 和 \(d_- = 1\)。
如你所见,玩家的起始位置取决于某个整数常数 \(m\)(\(1 \leq m \leq 1000\))……不幸的是,你也不知道它。
每轮之后,玩家会告诉你他现在是否位于 \(x = 0\)。
通过进行若干轮,你可以唯一确定玩家是好人、坏人还是丑人。请在不超过 \(30m\) 轮内完成。
在每个测试中,值 \(m\)、\(p\)、\(d_+\) 和 \(d_-\) 根据上述规则选择。它们预先固定,在检查过程中不会改变。
思路
假如 \(m\) 的限制为最大值(即 \(1000\times 30\)),那么我们有一个很显然的策略:往一个方向走 \(1000\) 步,再往另一个方向走 \(2000\) 步。
但是 \(m\) 的限制是动态的(\(30m\)),所以我们需要考虑逐步扩大搜索范围。
以下情况未考虑丑人,但是丑人仍可以使用此策略解决。
假如我们一开始往一个方向走了 \(a\) 步,那么这 \(a\) 步有两种情况:
-
离原点的距离缩小了 \(a\)
-
离原点的距离扩大了 \(2a\),此时需要往反方向再走 \(3a\) 步才能保证距离缩小 \(a\)。
因此我们每次都以最坏情况考虑,即每次走的步数都是上一次的 \(3\) 倍,直到达到原点,达到原点后的判断是简单的。
假设交互次数为 \(q\),可以证明 \(\forall m,q\le 30m\),过程略。
代码
#include <bits/stdc++.h>
using namespace std;
int x,y,len=1,nw;
void in(){
cin>>x;
if(x==0) return;
cout<<"+"<<endl,cin>>x;
cout<<"-"<<endl,cin>>y;
if(x+y==1){
cout<<"! ugly"<<endl;
exit(0);
}
else{
cout<<"-"<<endl;
cin>>x;
cout<<(x?"! good":"! bad")<<endl;
exit(0);
}
}
signed main(){
while(true){
for(int i=1;i<=len;i++)
cout<<(nw?'+':'-')<<endl,in();
nw=!nw,len*=3;
}
return 0;
}

浙公网安备 33010602011771号