码迷,mamicode.com
首页 > 其他好文 > 详细

UVA11261 Bishops

时间:2015-08-13 22:17:15      阅读:145      评论:0      收藏:0      [点我收藏+]

标签:思维题

给出一个n*n的棋盘和m个象,每个象能够覆盖它所在的对角线,问没有被覆盖的点有多少个

对于一头大象它可以覆盖它所在的从对角线和主对角线,但是些对角线可能相互交叉,因此不能直接求对角线上面的点的个数。n*n的暴力方法很好想出来,但是肯定超时。

我们可以把主对角线和从对角线保存下来,预处理好没有被覆盖的点,dp[i]表示第i条从对角线上面没有被覆盖的点,一共有2*n-1条从对角线。对于从对角线的上半部分,dp[i]初始化为dp[i-2]因为他们的奇偶性相同,则除去第i条从对角线的两个端点以外,如果第i-2条从对角线上的某个点被一条主对角线覆盖,那么它右下角对应的从对角线上的点也被覆盖。时间复杂度为O(N)。

技术分享

#include<cstdio>
#include<cstring>
#define MAXN 80005
using namespace std;
bool cover_positive[MAXN];//主对角线是否被覆盖
bool cover_negative[MAXN];//从对角线是否被覆盖
int dp[MAXN];//保存第i条从对角线有多少个点没有被覆盖
int n,m;
int main()
{
	int T;
	scanf("%d",&T);
	int cnt = 0;
	while(T--)
	{
		memset(cover_positive,0,sizeof cover_positive);
		memset(cover_negative,0,sizeof cover_negative);
		memset(dp,0,sizeof dp);
		scanf("%d%d",&n,&m);
		int x,y;
		for(int i = 1; i <= m; i++)
		{
			scanf("%d%d",&x,&y);
			cover_positive[n+x-y] = 1;
			cover_negative[x+y-1] = 1;
		}
		
		if(!cover_positive[n]) dp[2*n-1] = dp[1] = 1;//第n条主对角线没有被覆盖,因此第1和第2n-1条对角线上面有一个没有被覆盖的点
		for(int i = 2; i <= n; i++)
		{
			dp[i] = dp[i-2];//dp[i]由dp[i-2]转移过来,第i条对角线比第i-2条对角线多左下和右上2个点,
			//如果第i-2条对角线的其他点被覆盖,那么第i条对角线上的点也会被覆盖
			int num = n - i + 1;
			if(!cover_positive[num]) ++dp[i];
			if(!cover_positive[2*n-num]) ++dp[i];
		}
		for(int i = 2*n-2; i >= n+1; i--)
		{
			dp[i] = dp[i+2];//另外一半对角线与之前的一半相反
			int num = i - n + 1;
			if(!cover_positive[num]) ++dp[i];
			if(!cover_positive[2*n-num]) ++dp[i];
		}
		
		int ans = 0;
		for(int i = 1; i < 2*n; i++)
			if(!cover_negative[i])
				ans += dp[i];
		printf("Case #%d: %d\n",++cnt,ans);
	}
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

UVA11261 Bishops

标签:思维题

原文地址:http://blog.csdn.net/cqbzwja/article/details/47620667

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!