【2020.11.14提高组模拟】无尽之前 (game) 题解

【2020.11.14提高组模拟】无尽之前 (game) 题解

有趣的题面

题目背景

雏见泽,一个和平的,或者说本应和平的小村庄,却因连续四年的怪死事件而蒙上了阴 影。

无一例外,每年的事件都发生在棉流祭当晚。一人死亡,一人失踪。是御社神的作祟, 还是另有隐情?人们这样议论着。

六月已至,一年一度的棉流祭之火又将重新燃起。平日里冷清的集市渐渐热闹起来,人 们的欢声笑语环绕着这个宁静的小村庄。而同时,在不知名的角落里,也有些许不安的种子 在无声的发芽。

蓝色长发的少女站在山巅上,冷冷地看着山下即将发生的一切。

“这次,又将是谁呢?”

身后的人影无声地点头。

问题描述

这是开始前的故事。

羽入和小梨花在 \(n ∗ m\) 的棋盘上下棋,其中行从 \(1\)\(n\) 标号,列从 \(1\)\(m\) 标号。

棋盘上有两种棋子:车和兵。车每次可以往四个方向走任意格,直到在某个空地停下或 者碰到一个兵把兵吃掉并停下来。兵每次可以往四个方向走一格,要求格子是空地或者是车, 如果是车则将车吃掉。

现在羽入控制车,梨花控制兵,车初始在 \((x1, y1)\),终点在 \((x2, y2)\),如果车走到了终点 (无论下一步是否存活)则羽入获胜,否则若车被吃了或者羽入在 \(10^{100000}\) 步内无法获胜则梨花获胜。双方每次只能移动自己的某一个棋子走一步(也可以选择不移动)。

棋盘初始只有一个车,梨花在开始前可以选择在任意非车位置(包括终点)放兵,接着羽入先手操作车,之后两人轮流操作。

因为羽入除了会啊呜啊呜以外还很聪明,所以梨花想知道自己需要放的最少兵的数量, 使得两人都按照最优策略进行时自己可以获胜,如果无解输出 \(−1\)

题意简述

一人控制一个车,一人控制\(x\)个兵。控制车的人先走。给定棋盘大小\(n \times m\)、起点\((sx,sy)\)、终点\((ex,ey)\),问兵能不能阻止车走到终点,不能输出\(-1\),否则最小化\(x\)并输出。

吓人的数据范围

对于\(100\%\)的数据保证起点和终点不相同,\(n,m \le 300\),\(1\le x_1,x_2\le n\),\(1\le y_1,y_2\le m\)

数据点编号 \(n,m\le\)
\(1,2,3\) \(3\)
\(4,5,6\) \(50\)
\(7,8,9,10\) \(300\)

题目分析

看数据范围和题面中的\(10^{100000}\)会不会以为是个很难的东西?

其实(就是我太菜了),这题是一个模拟+分类讨论的思维题。我们可以从特殊到一般地讨论所有情况。

Subtask1

起点终点只差一步

那么兵无法摆在起点和终点之间,车可以一步到位,输出\(-1\)

image-20201117215607090

Subtask2

终点到所有边界的距离\(\le1\)

只可能出现在\(\le3\times3\)的地图上,终点到四周的距离才可能都\(\le1\)

只要放一个兵在终点,车不能走到兵的四个方向上,因此答案是\(1\)

image-20201117215955715

Subtask3

长度或宽度\(\le2\)

如果某一维\(=1\)就连放两个兵;

如果\(=2\)的话用两个兵把路堵死。

如果车把其中一个兵吃了,就会被另一个兵吃掉,因此答案是\(2\)

image-20201117220553065

Subtask3.5

长度或宽度\(=2\)且起点在终点九宫格的斜脚处

image-20201117220907254

因为正常情况下车不可能进入九宫格的。

三个兵放在起点和终点围成的矩形内,答案为3。

只用两个兵的话车可以往后退,同时压住兵不能移动,然后就可以获胜了。

image-20201117220957804

但是还是有特殊情况(特殊情况中的特殊情况了):(默认为\(2\)的是高度)若到左右两边某一边的距离为\(1\),车也是靠着那个角落的,则可以只用横放两个兵,答案为\(2\)

image-20201117221459266

Subtask4

终点到某个角落的切比雪夫距离\(\le1\)

切比雪夫距离指的是国际象棋中的国王从一个起点到终点需要走的步数。

容易推出,S到T的切比雪夫距离就是\(max(\Delta x,\Delta y)\)

只要在终点放一个,与终点相连的靠近起点的位置上放一个,车转不过来,因此答案为\(2\)

image-20201118084422740

Subtask4.5

起点和终点是对角线相邻的状态,类似于Subtask3.5。答案为3。

image-20201118084823803

Subtask5

其他的所有情况

放三个在终点、终点的九宫格内

image-20201118085031810

如图,假如白色九宫格中心是终点,那么对车的位置进行分类讨论。

无论车在哪种颜色中,兵都可以在相同或者更少的步数内走到安全的位置(保护中间的兵且如果车吃掉某个兵时会被另一个兵吃了)

Other Subtask

其实还是有一些没有考虑到的情况的。

\(n=m=3\)\(S\)=\((2,2)\)\(T\)在角落

答案为2,在两个对角各放一个。

......

也许还会有很多别的情况,以后想到再说吧。只有10个测试点没办法涵盖到所有情况的。

Code

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<queue>
#include<vector>
#define IL inline
#define re register
#define LL long long
#define ULL unsigned long long
#define re register
#define debug printf("Now is %d\n",__LINE__);
using namespace std;

template<class T>inline void read(T&x)
{
    char ch=getchar();
    while(!isdigit(ch))ch=getchar();
    x=ch-'0';ch=getchar();
    while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
}
inline int read()
{
	int x=0;
    char ch=getchar();
    while(!isdigit(ch))ch=getchar();
    x=ch-'0';ch=getchar();
    while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
    return x;
}
int G[55];
template<class T>inline void write(T x)
{
    int g=0;
    if(x<0) x=-x,putchar('-');
    do{G[++g]=x%10;x/=10;}while(x);
    for(re int i=g;i>=1;--i)putchar('0'+G[i]);putchar('\n');
}
int n,m,sx,sy,ex,ey,ans;
int main()
{
	freopen("game.in","r",stdin);
	freopen("game.out","w",stdout);
	cin>>n>>m>>sx>>sy>>ex>>ey;
	//Subtask1 
	if(abs(sx-ex)+abs(sy-ey)==1)
	{
		cout<<-1;
		return 0;
	}
	//Subtask2
	if(n<=3&&m<=3&&(ex-1<=1||n-ex<=1)&&(ey-1<=1||m-ey<=1))
	{
		cout<<1;
		return 0;
	}
	//Subtask3
	if(n<=2||m<=2)
	{
		//Subtask3.5
		if((n==2||m==2)&&abs(sx-ex)*abs(sy-ey)==1)
		{
			if(m==2)
			{
				if((sx==1||sx==n)&&(ex==2||ex==n-1))
				{
					cout<<2;
					return 0;
				}
			}
			if(n==2)
			{
				if((sy==1||sy==n)&&(ey==2||ey==m-1))
				{
					cout<<2;
					return 0;
				}
			}
			cout<<3;
			return 0;
		}
		cout<<2;
		return 0;
	}
	//Subtask4
	if(max(ex-1,ey-1)<=1||max(n-ex,m-ey)<=1||max(ex-1,m-ey)<=1||max(n-ex,ey-1)<=1)
	{
		//Subtask4.5
		if(abs(sx-ex)*abs(sy-ey)==1) cout<<3;
		else cout<<2;
		return 0;
	}
	//Other Subtask
	if(n==m&&m==3&&sy==sx&&sx==2&&(ex==1||ex==n)&&(ey==1||ey==m))
	{
		cout<<2;
		return 0;
	}
	cout<<3;
	return 0;
}
posted @ 2020-11-18 09:48  Vanilla_chan  阅读(289)  评论(0)    收藏  举报