HDU 5254 棋盘占领(暴力枚举)

百小度最近迷恋上了一款游戏,游戏里有一个n*m的棋盘,每个方格代表一个城池。
一开始的时候我们有g支军队,驻扎并占领了其中某些城池。然后我们可以在这些被占领城池的基础上,吞并占领周围的城池。


而其吞并占领的规则是这样的――一旦一个城池A相邻的上下左右四个城池中至少存在两个被占领,且这两个被占领的城池有公共点,那么城池A也将被占领。
比如我们用1表示初始的占领状态,0表示初始的未占领状态。
那么――

10

01


会最终会变成

11

11


而101则保持为101不变

现在告诉你一张地图一开始所有被占领城池的信息,问你最后多少个城池会被我们占领。

Input

第一行为T,表示输入数据组数。

下面T组数据,对于每组数据,
第一行是两个数n,m(1≤n,m≤500),表示国土的大小为n*m。


第二行是一个整数g(1≤g≤1000),表示我们一开始占领的城池数。
然后跟随g行,第i行一对整数x,y(1≤xn,1≤ym)

,表示占领的第i个城池的坐标。 

Output

对第i组数据,输出

Case #i:

然后输出一行,仅包含一个整数,表示最终有多少个城池被占领。

Sample Input

4
2 2
2
1 1
2 2
3 3
3
1 1
2 3
3 2
2 4
5
1 1
1 1
1 2
1 3
1 4
2 4
2
1 1
2 4

Sample Output

Case #1:
4
Case #2:
9
Case #3:
4
Case #4:
2

思路:暴力求解,不断的对整个棋盘进行刷新,当某一遍刷新完成之后,占领的城池个数并没有增加,那么以后也肯定不会在增加了,跳出循环即可。

AC代码:

#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=500+10;
int G[maxn][maxn];
int n,m;
int check(int x,int y){
    if(y-1>=1 && G[x][y-1]  || y+1<=m && G[x][y+1]){
    	if(x-1>=1 && G[x-1][y]){
         G[x][y]=1;
		return 1;}
    	else if(x+1<=n && G[x+1][y]){
		G[x][y]=1;
		return 1;}
	}	
	return 0 ;
}

int main(){
	int T;
	scanf("%d",&T);
	int count=0; 
	while(T--){
		scanf("%d%d",&n,&m);
		int g;
		scanf("%d",&g);
		int start=0;
	    memset(G,0,sizeof(G));
	    for(int i=0;i<g;i++){
	    	int x,y;
	    	scanf("%d%d",&x,&y);
	    	if(G[x][y]==0){
	    		G[x][y]=1;
	    		start++;
			}
		}
		
		int cnt=0;
		while(true){
			int tmp=0;    //如果当前遍历一个都没有占领,那么以后也不可能占领了,退出循环 
		for(int i=1;i<=n;i++){
			for(int j=1;j<=m;j++){
				if(G[i][j]==0){
					int flag=check(i,j);
					if(flag)tmp++;
				}
			}
		 }
		 if(tmp==0)break;
		 cnt+=tmp;
		}		
		printf("Case #%d:\n",++count);
		printf("%d\n",cnt+start);
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

柏油

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值