CF1557E Assiut Chess 题解

发布时间 2023-06-20 15:11:25作者: llzer

题面翻译

本题是一道交互题。

本题需要你编写一个国际象棋中单后杀王的程序,和交互库对弈。 本题的规则和一般国际象棋中的规则有所不同,请认真阅读。

国际象棋棋盘是 \(8\times 8\) 的正方形网格。本题中,所有行从上到下分别编为 \(1\sim 8\) 行,所有列从左到右分别编为 \(1\sim 8\) 列;记同时处在第 \(r\) 行、第 \(c\) 列的格子为格子 \((r,c)\)

在游戏的开始,你需要确定并告知交互库皇后的初始坐标。接着,交互库会秘密地把国王放至棋盘上任何一个格子。然后,游戏开始,双方轮流走棋,由交互库先行。

皇后的 行走范围 为所有和皇后同行、同列或者同在一条 \(45^\circ\) 斜线上的格子。也就是说,设皇后当前在格子 \((r,c)\),则皇后下一步能走到格子 \((x,y)\),当且仅当 \((r,c)\neq (x,y)\),且 \(r=x\)\(c=y\)\(|r-x|=|c-y|\)。注意:在一步棋中,不允许将皇后停在原地不动。

国王的 行走范围 为其紧邻的 \(8\) 个格子。也就是说,也就是说,设国王当前在格子 \((r,c)\),则国王下一步能走到格子 \((x,y)\),当且仅当 \((r,c)\neq (x,y)\),且 \(\max \{|r-x|,|c-y|\}=1\)国王不能停在原地不动,不能走入皇后所在的格子,也不能走入皇后的行走范围中。 如果国王无法移动,那么游戏结束,你获得胜利。特别地,如果游戏开始时国王和皇后处于同一位置,那么你直接获胜。

游戏开始后,你和交互库将通过输入输出交流各自走棋的位置(具体格式见下文)。你需要在 \(130\) 步内获得胜利,如果你在行走 \(130\) 步后国王仍有合法移动,那么视作你失败。你需要写一个程序,在规定的步数内获得胜利。

交互细节

本题一个测试点含多组测试数据。你需要首先从标准输入中读入一个正整数 \(t(1\leq t\leq 60)\),表示测试数据组数。你们接下来将进行 \(t\) 次游戏。

每次游戏开始时,你需要先输出两个正整数 \(x\ y\),表示你选择的皇后坐标。接着交互库会选择国王的坐标(但不会告诉你)。接着从交互库开始,双方轮流行动。

当交互库行动时,你需要读入一个字符串 \(S\)\(S\) 的取值可能有如下几种:

  • Done:表示交互库无法找到合适的着法,你获胜。如果是最后一组数据则请退出程序;否则请准备下一组数据。
  • RightLeftUpDownDown-RightDown-LeftUp-RightUp-Left:分别表示国王向右、左、上、下、右下、左下、右上、左上走了一步。

当你行动时,你需要输出两个整数 \(x\ y\) 表示你移动到的坐标。你需要保证坐标合法。

题解

考虑初始将后放置在\((1,1)\)

我们需要时刻保证王在后下方,显然完成放置后之后的 \(1\) 个时刻是满足的。

之后如何保证?

首先王不可能跟后处在同一行。

若王在后下方 \(2\) 行及以上,后可以向下一行。

若王向下一行,则后也可以向下一行。

若王在后下方 \(1\) 行,后不能向下,因为王有可能可以向上 \(1\) 行,这样后就在王下方了。

怎么办?

设当前后处在第 \(x\) 行,王处在第 \(x+1\)\((1<=x<=7)\)。只需将后移动至 \((x,1)\),然后后每次向右一格,在移动至 \((x,8)\) 之前,无视王左右移动,总有一个时刻王会向下,那么后也向下即可。

王向上怎么办?若王处在后下方 \(2\) 行以上,向上是无影响的,若王恰好处在后下方 \(2\) 行,向上后就到了后下方 \(1\) 行。

注意到王至多向上七次,因此每次王向上之后将后移至后所在当前行的最左侧,然后每次向右一格直至王向下即可。

所以整个流程就是初始将后放置在 \((1,1)\),对于每一行,后都从 \((x,1)\) 移到 \((x,8)\),若王向下,后也向下,然后移至最左侧即可,若王向上,后移至最左侧即可。

总的步数不超过 \(8*8+7*8=120\),可以通过本题,实际上这很松,因为后不可能每次都需要从最左侧移至最右侧,即使王走到最右侧,后在第 \(7\) 列时王也得向下走了。

如果后位于 \((x,1)\) 时就需要向下,可以直接走到 \((x+1,2)\) ,能省点步数,不过没什么关系。

代码

#include<bits/stdc++.h>
#define For(i,l,r) for(int i=(l);i<=(r);++i)
#define FF fflush(stdout)
using namespace std;
int now_x,now_y;
string query()
{
	printf("%d %d\n",now_x,now_y);
	FF;
	string opt;
	cin>>opt;
	return opt;
}
void solve()
{
	now_x=1,now_y=1;
	bool flag=false;
	string opt=query();
	if(opt=="Done")
		return;
	while(opt!="Done")
	{
		if((opt=="Up") || (opt=="Up-Left") || (opt=="Up-Right") || (flag==true))
		{
			if(now_y==1)
				now_y=2;
			else
				now_y=1;
			flag=false;
			opt=query();
		}
		else if((opt=="Down") || (opt=="Down-Left") || (opt=="Down-Right"))
		{
			flag=true;
			++now_x;
			opt=query();
		}
		else
		{
			if(now_y==8)
			{
				flag=true;
				++now_x;
			}
			else
				++now_y;
			opt=query();
		}
	}
	return;
}
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
		solve();
	return 0;
}