首页 > 其他分享 >[省选联考2023] 过河卒

[省选联考2023] 过河卒

时间:2023-04-29 09:34:26浏览次数:48  
标签:省选 样例 联考 黑方 int 棋子 2023 黑棋子 红方

[省选联考 2023] 过河卒

题目背景

棋盘上有一个过河卒,需要走到底线。卒行走的规则是可以向左移动一格,向右移动一格或者向前移动一格。同时在棋盘上有两个另一方的棋子,需要拦截这个卒走到底线。这两个棋子的走法和帅一致,可以走到前后左右四个方向上相邻的格子。因此本题可以称为“帅拦过河卒”。

题目描述

有一个 \(n\) 行 \(m\) 列的棋盘。我们用 \((i,j)\) 表示第 \(i\) 行第 \(j\) 列的位置。棋盘上有一些 障碍,还有一个黑棋子和两个红棋子。

游戏的规则是这样的: 红方先走,黑方后走,双方轮流走棋。红方每次可以选择一个红棋子,向棋盘的相邻一格走一步。具体而言,假设红方选择的这个棋子位置在 \((i,j)\),那么它可以走到 \((i-1,j),(i+1,j),(i,j-1),(i,j+1)\) 中的一个,只要这个目的地在棋盘内且没有障碍且没有红方的另一个棋子。

黑方每次可以将自己的棋子向三个方向之一移动一格。具体地,假设这个黑棋子位置在 \((i,j)\),那么它可以走到 \((i-1,j),(i,j-1),(i,j+1)\) 这三个格子中的一个,只要这个目的地在棋盘内且没有障碍。

在一方行动之前,如果发生以下情况之一,则立即结束游戏,按照如下的规则判断胜负(列在前面的优先):

  • 黑棋子位于第一行。此时黑方胜。

  • 黑棋子和其中一个红棋子在同一个位置上。此时进行上一步移动的玩家胜。

  • 当前玩家不能进行任何合法操作。此时对方胜。

现在假设双方采用最优策略,不会进行不利于自己的移动。也就是说:

  • 若存在必胜策略,则会选择所有必胜策略中,不论对方如何操作,本方后续获胜所需步数最大值最少的操作。
  • 若不存在必胜策略,但存在不论对方如何行动,自己都不会落败的策略,则会选择任意一种不败策略。
  • 若不存在不败策略,则会选择在所有策略中,不论对方如何操作,对方后续获胜所需步数最小值最大的操作。

如果在 \(100^{100^{100}}\) 个回合之后仍不能分出胜负,则认为游戏平局。请求出游戏结束时双方一共移动了多少步,或者判断游戏平局。

输入格式

本题有多组测试数据

输入的第一行包含两个整数 \(\text{id},T\),分别表示测试点编号和数据组数。特别地,样例的 \(\text{id}\) 为 \(0\)。

接下来包含 \(T\) 组数据,每组数据的格式如下:

第一行包含两个正整数 \(n,m\),表示棋盘的行数和列数。

接下来 \(n\) 行,每行包含一个长度为 \(m\) 的字符串,其中第 \(i\) 行的第 \(j\) 个字符表示棋盘上 \((i,j)\) 这个位置的状态。

在这些字符中:\(\texttt{'.'}\) 表示空位;\(\texttt{'\#'}\) 表示障碍物;\(\texttt{'X'}\) 表示黑棋;\(\texttt{'O'}\) 表示红棋。

保证黑棋恰好有一个,红棋恰好有两个,且黑棋不在第一行。

输出格式

对于每组数据,输出一行字符串。

如果游戏平局,请输出一行 \(\texttt{"Tie"}\)。

如果红方胜,请输出一行 \(\texttt{"Red t"}\)。其中 \(\texttt{t}\) 为游戏结束时双方移动的步数之和。显然这应该是一个奇数。

如果黑方胜,请输出一行 \(\texttt{"Black t"}\)。其中 \(\texttt{t}\) 为游戏结束时双方移动的步数之和。显然这应该是一个偶数。

注意,请输出双引号内的字符串,不包含双引号。

样例 #1

样例输入 #1

0 5
4 5
...#O
.#..#
#O#..
.#..X
3 3
#.#
O.O
.X.
3 3
O..
.#X
.O.
5 5
.....
.....
..O..
#..#.
O#.X.
9 9
...######
.#.......
.#######.
.#.#.....
.#O#.####
.#.#.....
.#######.
.#X......
.O.......

样例输出 #1

Black 0
Black 2
Black 2
Tie
Red 75

样例 #2

样例输入 #2

见附件中的 zu/zu2.in

样例输出 #2

见附件中的 zu/zu2.ans

提示

【样例 1 解释】

第一组数据,红方第一步没有可行的移动,所以黑方胜。

第二组数据,无论第一步红方怎么移动,黑方都可以在下一步让黑棋子与红棋子在同一个位置。

第三组数据,无论第一步红方怎么移动,黑方都可以将自己的棋子往上移动一枚来达成胜利。

第四组数据,有一个红棋子不能动。另一个红棋子可以在第三行移动来防止黑棋子进入第一行。黑棋子也可以一直在第五行移动。如果红棋子到达第五行,黑棋子可以选择从另一边逃走。

第五组数据,在最后一行的那个红棋子可以从左边绕一圈抓住黑棋子。注意另一个红棋子可以移动。

【样例 2 解释】

这个样例中的每一组数据都满足测试点 \(5\) 到 \(13\) 中某一个测试点的限制。

【子任务】

对于所有的数据,保证:\(1 \leq T \leq 10 ; 2 \leq n \leq 10 ; 1 \leq m \leq 10 ; \text{id}\) 等于测试点编号。

对于每组数据保证:棋盘上的黑棋恰好有一个,红棋恰好有两个,且黑棋不在第一 行。

  • 测试点 \(1 \sim 4\):保证要么平局,要么红方在开始时无法移动。

  • 测试点 \(5 \sim 6\):保证 \(n \geq 4\) 。保证棋盘上第 \(n-1\) 行的每一个格子都是障碍物,且 棋盘上其他行没有障碍物。保证黑棋在前 \(n-2\) 行,有一个红棋在前 \(n-2\) 行,另一个红棋在第 \(n\) 行。

  • 测试点 \(7 \sim 9\):保证 \(m=1\)。

  • 测试点 \(10 \sim 13\):保证要么平局,要么存在策略可以在 \(9\) 步之内结束游戏。

  • 测试点 \(14 \sim 20\):无特殊限制。

范围这么小,随便设dp状态了。
定义 \(dp_{x1,y1,x2,y2,x3,y3,0/1}\) 表示现在红棋在点 \((x1,y1)\),黑棋分别在 \((x2,y2)\) 和 \((x3,y3)\),现在是 Alice/Bob,是谁胜。

会发现这个dp转移有环,考虑使用bfs的方式转移。

但是从初始状态进行bfs,其实很难处理。所以考虑从最终状态(也就是确定了是谁赢的状态)转移回来。把所有已经确定的状态入队。然后对于一个红方的棋子,如果他能到达的状态有红方必胜的状态,那肯定是红方必胜。不然如果全部状态是黑方必胜,那么这个点才是黑方必胜。

没有搜到的点呢?自然是平局了。
警示:两个红色棋子在同一位置上也是不合法状态

#include<bits/stdc++.h>
using namespace std;
const int N=11,INF=2e9,dx[]={0,-1,0,1},dy[]={-1,0,1,0};
int t,dp[N][N][N][N][N][N][2],ct[N][N][N][N][N][N][2],f[N][N][N][N][N][N][2],l,r,n,hjh,m,mp[N][N],nww,nw,pp,mx,mn,tfl,ax,ay,bx,by,cx,cy,fl;//f:0:平局 1:黑 2:红  dp:0:黑 1:红 
char str[N];
struct node{
	int ax,ay,bx,by,cx,cy,t;
}q[N*N*N*N*N*N*2];
inline int ok(int ax,int ay,int bx,int by,int cx,int cy)
{
	return ax&&ax<=n&&bx&&bx<=n&&cx&&cx<=n&&ay&&ay<=m&&by&&by<=m&&cy&&cy<=m&&(bx^cx||by^cy)&&!mp[ax][ay]&&!mp[bx][by]&&!mp[cx][cy];
}
void trd(int ax,int ay,int bx,int by,int cx,int cy,int t)
{
	if(ok(ax,ay,bx,by,cx,cy)&&!f[ax][ay][bx][by][cx][cy][t])
	{
		if(nw==t+1)
		{
			dp[ax][ay][bx][by][cx][cy][t]=hjh+1;
			f[ax][ay][bx][by][cx][cy][t]=t+1;
			q[++r]=(node){ax,ay,bx,by,cx,cy,t};
			return;
		}
		--ct[ax][ay][bx][by][cx][cy][t];
		if(!ct[ax][ay][bx][by][cx][cy][t])
		{
			f[ax][ay][bx][by][cx][cy][t]=(!t)+1;
			dp[ax][ay][bx][by][cx][cy][t]=hjh+1;
			q[++r]=(node){ax,ay,bx,by,cx,cy,t};
		}
	}
}
void bfs()
{
	l=1,r=0;
	for(int ax=1;ax<=n;ax++){
	for(int ay=1;ay<=m;ay++){
	for(int bx=1;bx<=n;bx++){
	for(int by=1;by<=m;by++){
	for(int cx=1;cx<=n;cx++){
	for(int cy=1;cy<=m;cy++){
		if(!ok(ax,ay,bx,by,cx,cy))
			continue;
		if(f[ax][ay][bx][by][cx][cy][0])
		{
			q[++r]=(node){ax,ay,bx,by,cx,cy,0};
			dp[ax][ay][bx][by][cx][cy][0]=dp[ax][ay][cx][cy][bx][by][0]=0;
		}
		if(f[ax][ay][bx][by][cx][cy][1])
		{
			q[++r]=(node){ax,ay,bx,by,cx,cy,1};
			dp[ax][ay][bx][by][cx][cy][1]=dp[ax][ay][cx][cy][bx][by][1]=0;
		}
	}}}}}}
	while(l<=r)
	{
		int ax=q[l].ax,ay=q[l].ay,bx=q[l].bx,by=q[l].by,cx=q[l].cx,cy=q[l].cy,t=q[l].t;
		nw=f[ax][ay][bx][by][cx][cy][t];
		hjh=dp[ax][ay][bx][by][cx][cy][t];
		if(ax==::ax&&ay==::ay&&bx==::bx&&by==::by&&cx==::cx&&cy==::cy&&t)
			break; 
		++l;
		if(!t)
		{
			trd(ax,ay,bx+1,by,cx,cy,1);
			trd(ax,ay,bx-1,by,cx,cy,1);
			trd(ax,ay,bx,by+1,cx,cy,1);
			trd(ax,ay,bx,by-1,cx,cy,1);
			trd(ax,ay,bx,by,cx+1,cy,1);
			trd(ax,ay,bx,by,cx-1,cy,1);
			trd(ax,ay,bx,by,cx,cy+1,1);
			trd(ax,ay,bx,by,cx,cy-1,1);
		}
		else
		{
			trd(ax+1,ay,bx,by,cx,cy,0);
			trd(ax,ay+1,bx,by,cx,cy,0);
			trd(ax,ay-1,bx,by,cx,cy,0);
		}
	}
}
int main()
{
// 	freopen("zu.in","r",stdin);
// 	freopen("zu.out","w",stdout);
	scanf("%*d%d",&t);
	while(t--)
	{
		scanf("%d%d",&n,&m);
		bx=by=0;
		for(int i=1;i<=n;i++)
		{
			scanf("%s",str+1);
			for(int j=1;j<=m;j++)
			{
				if(str[j]=='#')
					mp[i][j]=1;
				else
					mp[i][j]=0;
				if(str[j]=='X')
					ax=i,ay=j;
				if(str[j]=='O')
				{
					if(bx)
						cx=i,cy=j;
					else
						bx=i,by=j;
				}
			}
		}
		memset(f,0,sizeof(f));
		memset(ct,0,sizeof(ct)); 
		for(int ax=1;ax<=n;ax++)
		{
			for(int ay=1;ay<=m;ay++)
			{
				for(int bx=1;bx<=n;bx++)
				{
					for(int by=1;by<=m;by++)
					{
						for(int cx=1;cx<=n;cx++)
						{
							for(int cy=1;cy<=m;cy++)
							{
								if(!ok(ax,ay,bx,by,cx,cy))
									continue;
								if(ax==1)
									f[ax][ay][bx][by][cx][cy][1]=f[ax][ay][bx][by][cx][cy][0]=1;
								else if(ax==bx&&ay==by||ax==cx&&ay==cy)
								{
									f[ax][ay][bx][by][cx][cy][1]=1;
									f[ax][ay][bx][by][cx][cy][0]=2;
								}
								else
								{
									int p=0;
									for(int i=0;i<4;i++)
										ct[ax][ay][bx][by][cx][cy][1]+=ok(ax,ay,bx+dx[i],by+dy[i],cx,cy)+ok(ax,ay,bx,by,cx+dx[i],cy+dy[i]);
									if(!ct[ax][ay][bx][by][cx][cy][1])
										f[ax][ay][bx][by][cx][cy][1]=1;
									ct[ax][ay][bx][by][cx][cy][0]=ok(ax-1,ay,bx,by,cx,cy)+ok(ax,ay+1,bx,by,cx,cy)+ok(ax,ay-1,bx,by,cx,cy);
									if(!ct[ax][ay][bx][by][cx][cy][0])
									f[ax][ay][bx][by][cx][cy][0]=2;
								}
							}
						}
					}
				}
			}
		}
		bfs();
		int nw=f[ax][ay][bx][by][cx][cy][1];
		if(!nw)
			puts("Tie");
		else 
		{
			if(nw==1)
				printf("Black ");
			else
				printf("Red ");
			printf("%d\n",dp[ax][ay][bx][by][cx][cy][1]);
		}
	}
}
···

标签:省选,样例,联考,黑方,int,棋子,2023,黑棋子,红方
From: https://www.cnblogs.com/mekoszc/p/17363577.html

相关文章

  • 【愚公系列】2023年04月 .NET CORE工具案例-.NET Core使用MiniWord
    (文章目录)前言MiniWord模板引擎的主要功能是根据模板,生成对应的Word文档。支持跨平台,项目采用类似Vue、React模板方式,在模板定义相应的变量,再结合数据,快速生成Word文件。MiniWord官网:https://github.com/mini-software/MiniWord一、.NETCore使用MiniWord1.安装包MiniWord......
  • 2023/4/28读书笔记
       今天,上了计算机网络,学习了运输层的相关知识,简单介绍了UDP与TCP的协议与区别,一个可靠,一个尽可能交付,学习了端口与运输层为应用进程提供逻辑通信。后来,在概率论上学了了方差的定义,计算方法,常见方差,方差性质,标准差,标准化,协方差COV的定义,计算方法,性质,与相关系数。......
  • 总结20230428
    代码时间(包括上课):1h代码量(行):30行博客数量(篇):1篇相关事项:1、今天上午第一节课是计算机网络,开启了运输层的新篇章。2、今天上午第二节是概率论,讲的是概率论的方差、协方差、相关系数等知识。3、今天晚上打算在学一点Javaweb的知识。......
  • 2023冲刺清北营8
    T1内鬼由于两名内鬼的行动互不干扰,因此可以单独求解后暴力合并。很容易想到一种dp做法,设\(f_{i,S}\)表示当前位于第\(i\)个点,当前刀掉的人组成的集合为\(S\)时的最短时间,转移时考虑通过一条边或留在此处继续刀人,很容易使用Dijikstra进行转移,然而……它TLE了……考......
  • 每日总结2023-04-28
    今天完成了ANdroid中的找回密码packagecom.example.math;/**找回界面*/importstaticandroid.widget.Toast.LENGTH_SHORT;importandroidx.appcompat.app.AppCompatActivity;importandroid.os.Bundle;importandroid.os.Handler;importandroid.view.View;import......
  • 2023 4 28
     ......
  • 2023-04-28:将一个给定字符串 s 根据给定的行数 numRows 以从上往下、从左到右进行 Z
    2023-04-28:将一个给定字符串s根据给定的行数numRows以从上往下、从左到右进行Z字形排列比如输入字符串为"PAYPALISHIRING"行数为3时,排列如下PAHNAPLSIIGYIR之后,你的输出需要从左往右逐行读取,产生出一个新的字符串"PAHNAPLSIIGYIR"请你实现......
  • 2023/4/28
    R6-2复数的加减运算(运算符重载)分数 30全屏浏览题目作者 fpc单位 内蒙古师范大学###复数加减(运算符重载)声明一个复数类CComplex(类私有数据成员为double型的real和image)定义构造函数,用于指定复数的实部与虚部。重载<<运算符,以格式real+imagei的格......
  • 【考后总结】NOI 统一省选 2023
    文化课补完了,但是考试考炸了,所以来补题。D1T1火车站station实际上只需要判断从\(x\)能否一直向一个方向移动且每个位置能不能作为这个方向的终点站。区间覆盖差分一下即可。提交记录:Submission-QOJD1T2城市建造cities一个连通块中只能有一个点被选中。由于连通块大......
  • 【考后总结】NOI 统一省选 2023
    文化课补完了,但是考试考炸了,所以来补题。D1T1火车站station实际上只需要判断从\(x\)能否一直向一个方向移动且每个位置能不能作为这个方向的终点站。区间覆盖差分一下即可。提交记录:Submission-QOJD1T2城市建造cities一个连通块中只能有一个点被选中。由于连通块大......