[CF1023E]Down or Right

10 篇文章 0 订阅

题目

传送门 to CF

传送门 to luogu

思路

先给出结论:

  1. 从左上角试探着往右下角走,每次优先向下。
  2. 从右下角试探着往左上角走,每次优先向左。

为什么这样是正确的呢?观察步骤一形成的路线(假设步骤一可以走完,走到右下角 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) (2n2)次即可。见代码。

代码

#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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值