【noi.ac】追捕大象

题目

在一块平原上有一头大象。

平原被分成n×mn×m个格子。初始时大象位于(1,1)(1,1)。每一秒,大象会移动到一个相邻的格子上(四连通),但不会移动到平原外面。由于你视力不好,你无法知道大象每次移动到哪个格子上。

你可以使用火球术来攻击地面。每次释放火球术,你可以攻击任意多个格子。每个格子只能被攻击一次。大象不能移动到被攻击过的格子上,如果大象相邻的格子都无法移动,那么它会停在原地不动。

你的目标是最后只剩下一个格子没有被火球术攻击过,然后你去那里活捉大象。在此之前,你必须保证你的火球术不会击中大象。由于大象的战斗力十分强大,只有在某些格子中你才能抓住大象。

然而,由于你魔法水平不高,在使用火球术前你需要进行蓄势。第一次蓄势的时间至少为n+mn+m秒,接下来每次蓄势时间都要比上次长。蓄势时间必须是整数秒。你希望最小化最后一次的蓄势时间。

注意:每一秒大象先移动,接着你才会释放火球术。也就是说,如果你第一次的蓄势时间为n+mn+m秒,那么大象已经移动了n+mn+m次。

Input
第一行包含两个整数 n,mn,m。

接下来 nn 行每行 mm 个数,每个数只能是 0 或 1。第 i+1i+1 行第 jj 列的数表示 在(i,j)(i,j)这个格子中,你能否抓住大象(1 表示能,0 表示不能)。

Output
输出若干行,每行表示释放一次火球术。

每行第一个整数表示蓄势时间,接下来若干个整数表示攻击的格子,第 ii 行第 jj 列的格子编号为(i−1)∗m+j(i−1)∗m+j。每行最后输出一个 0。

如果无解输出一行一个整数−1−1。

Examples
3 3
1 1 1
1 1 1
1 1 1
7 1 3 7 9 0
9 2 4 6 8 0
Notes
alt

特殊条件A:在所有格子中,你都能抓住大象。

特殊条件B:至少存在一个格子,你可以抓住大象。

对于每个测试点,如果这个测试点无解并且你判断对了,得5分。

如果这个测试点有解,记这个测试点最优策略的答案为ansans:

如果你的答案=ans=ans,得5分;

如果你的答案≤ans+2≤ans+2,得4分;

如果你的答案≤ans+4≤ans+4,得3分;

如果你的答案≤2ans≤2ans,得2分;

如果你的答案≤108≤108,得1分。

满足多个条件取最高分。

思路

对格子进行黑白染色,那么由步数的奇偶可以推断出大象所在格
子的颜色,然后删去另一种颜色的格子,但要保证删去之后,剩
余的格子依旧联通。
我们将这个过程反过来,一开始只有一个格子,每次增加若干个
同样颜色的格子,同时保证联通。由于我们想让步数尽量少,因
此我们会一圈一圈往外加。从一个格子加满整个棋盘的步数,就
是它到四个顶点的曼哈顿距离的最大值。
注意到除了第一次以外,之后的每一次蓄势时间都是奇数。假设
(1, 1) 为黑,那么第一次删黑格就是奇数,删白格就是偶数。当
n, m 都是偶数时,如果两种方法步数一样,但第一种方法第一次
删黑格,第二种方法第一次删白格,那么第二种方法最终相当于
少了一步。
时间复杂度 O(nm)

代码

#include<bits/stdc++.h>
using namespace std;
const int N=1077;
int n,m,x,y,cc=0;
vector<int> ans[N*2];
int solve(int x,int y){return max(x-1,n-x)+max(y-1,m-y);}
int main()
{
	scanf("%d%d",&n,&m);x=-1;y=-1;int k=(n+m)&1;
	for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)
	{
		int o,t=solve(i,j);scanf("%d",&o);if(!o)continue;
		if((x==-1&&y==-1)||t<solve(x,y)||(t==solve(x,y)&&(((i+j)&1)^(t&1))!=k))x=i,y=j;
	}
	for(int i=1;i<=n;i++) for(int j=1;j<=m;j++)ans[abs(i-x)+abs(j-y)].push_back(++cc);
	int p=n+m,ff=1;
	for(int i=n+m;i;i--) if(ans[i].size())
	{
		if(ff)
		{
			ff=0;p+=((x+y+i)&1)^k^1;
			printf("%d ",p);if(!(p&1))p--;
		}
		else{p+=2;printf("%d ",p);}
		for(int j=0;j<ans[i].size();j++)printf("%d ",ans[i][j]);
		puts("0");
	}
}
发布了809 篇原创文章 · 获赞 396 · 访问量 15万+

猜你喜欢

转载自blog.csdn.net/Eric1561759334/article/details/105506812