题目
思路
先给出结论:
- 从左上角试探着往右下角走,每次优先向下。
- 从右下角试探着往左上角走,每次优先向左。
为什么这样是正确的呢?观察步骤一形成的路线(假设步骤一可以走完,走到右下角 T T T 停止)。
由于我是优先向下行动,所以红色部分一定是不可以走的(可以将地图想象成没有边界,只是外面的格子都不可以通过)。
红色部分恰好形成了一堵墙。将这些红色部分投影到横轴上,你会发现: [ x s , x t ] [x_s,x_t] [xs,xt] 被它们填满了!
所以,红色的格子及其下方,不存在任何一条 S S S 到 T T T 的路径。
于是我们把这些格子扔掉,重新看这张图——
此时,如果从 T T T 出发,一直优先向左走,一定会沿着这条路走下去。因为这条路恰好是“地图”的边缘。你不能做到更靠左了。当然,你也不会走上其他的路。
其实只需要查询 ( 2 n − 2 ) (2n-2) (2n−2)次即可。见代码。
代码
#include <cstdio>
#include <iostream>
#include <vector>
using namespace std;
inline int readint(){
int a = 0; char c = getchar(), f = 1;
for(; c<'0' or c>'9'; c=getchar())
if(c == '-') f = -f;
for(; '0'<=c and c<='9'; c=getchar())
a = (a<<3)+(a<<1)+(c^48);
return a*f;
}
const int MaxN = 505;
char ans[MaxN<<1]; int n;
char what_i_get[MaxN];
bool query(int lx,int ly,int rx,int ry){
printf("? %d %d %d %d\n",lx,ly,rx,ry);
fflush(stdout); // 清除缓存
scanf("%s",what_i_get);
if(*what_i_get == 'Y') return true;
if(*what_i_get == 'N') return false;
return *(what_i_get-1); // RE
}
void DR(){ // down and right
int x = 1, y = 1, i = 0;
while((n-x)+(n-y) > (n-1))
if(x != n and query(x+1,y,n,n))
++ x, ans[i ++] = 'D';
else ++ y, ans[i ++] = 'R';
}
void LU(){ // left and up
int x = n, y = n, i = (n<<1)-2;
while((x-1)+(y-1) > (n-1))
if(y != 1 and query(1,1,x,y-1))
-- y, ans[-- i] = 'R';
else -- x, ans[-- i] = 'D';
}
int main(){
n = readint();
DR(), LU();
printf("! %s\n",ans);
return 0;
}