【百度之星初赛2】棋盘占领(深搜|广搜)

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


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


10

01

会最终会变成

11

11

而101则保持为101不变

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

Input

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

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


第二行是一个整数 g(1g1000) ,表示我们一开始占领的城池数。
然后跟随g行,第i行一对整数 x,y(1xn,1ym) ,表示占领的第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

http://acm.hdu.edu.cn/showproblem.php?pid=5254

#include<iostream>    
#include<algorithm>    
#include<string>    
#include<map>    
#include<vector>    
#include<cmath>    
#include<queue>    
#include<string.h>    
#include<stdlib.h>    
#include<cstdio>    
#define LL long long    
#define MP make_pair  
#define FOR(i,n) for(int i=0;i<(n);++i)  
using namespace std;   
typedef long double LD;  
typedef pair<int, int> PII;  
typedef pair<PII, int> PIII;  
typedef pair<LL, LL> PLL;  
typedef pair<LL, int> PLI;  
typedef pair<LD, LD> PDD;  
int vis[505][505];  
const int dx[] = {-1,0,1,0};  
const int dy[] = {0,1,0,-1};  
int main(){  
    int t;  
    scanf("%d",&t);  
    while(t--){  
        int n,m;  
        scanf("%d %d",&n,&m);  
        FOR(i,n) FOR(j,m) vis[i][j] = 0;  
        int g;  
        scanf("%d",&g);  
        queue<PII> q;  
        FOR(i,g){  
            int x,y;  
            scanf("%d %d",&x,&y);  
            vis[x-1][y-1] = 1;  
            q.push(MP(x-1,y-1));  
        }  
        while(!q.empty()){  
            PII p = q.front();q.pop();  
            for(int i = 0;i<4;i++){  
                int nx = p.first+dx[i];  
                int ny = p.second+dy[i];  
                if(nx>=0&&nx<n&&ny>=0&&ny<m&&!vis[nx][ny]){  
                    for(int j=0;j<4;j++){ 
                        if(abs(i-j)!=1&&abs(i-j)!=3)   //两个1只能是斜对角
                            continue; 
                        int nnx = nx+dx[j];  
                        int nny = ny+dy[j];  
                        if(nnx>=0&&nnx<n&&nny>=0&&nny<m&&vis[nnx][nny]){  
                                vis[nx][ny] = 1;  
                                q.push(MP(nx,ny));  
                                break;  
                        }
                    }  
                }  
            }  
        }  
        int ans = 0;  
        FOR(i,n) FOR(j,m) if(vis[i][j]) ans++;  
        static int ca = 1;  
        printf("Case #%d:\n%d\n",ca++,ans);  
    }  
    return 0;  
}

#include<iostream>  
#include<cstdio>  
#include<cstring>  
#include<string>  
#include<cstdlib>  
#include<algorithm>  
#include<cmath>  
using namespace std;  
int n,m;
int x[502][502];
int vis[502][502]; 
void dfs(int p,int q){
	if(vis[p][q]==1||x[p][q]==1||p<1||p>n||q<1||q>m)
		return;
	if(x[p+1][q]==1&&x[p][q+1]==1){
		x[p][q]=1;
		dfs(p-1,q);
		dfs(p,q-1);
	}
	if(x[p+1][q]==1&&x[p][q-1]==1){
		x[p][q]=1;
		dfs(p-1,q);
		dfs(p,q+1);
	}
	if(x[p-1][q]==1&&x[p][q+1]==1){
		x[p][q]=1;
		dfs(p+1,q);
		dfs(p,q-1);
	}
	if(x[p-1][q]==1&&x[p][q-1]==1){
		x[p][q]=1;
		dfs(p+1,q);
		dfs(p,q+1);
	}
}
int main(){  
	int t;
	scanf("%d",&t);
	int cnt=0;
	while(t--){
		scanf("%d %d",&n,&m);  
		memset(x,0,sizeof(x));
		memset(vis,0,sizeof(vis));
		int p,a,b;
		scanf("%d",&p);
		for(int i=0;i<p;++i){
			scanf("%d %d",&a,&b);
			x[a][b]=1;
		}
		for(int i=1;i<=n;++i){
			for(int j=1;j<=m;++j){
				if(vis[i][j]==0&&x[i][j]==0)
					dfs(i,j);
			}
		}
		int s=0;
		for(int i=1;i<=n;++i){
			for(int j=1;j<=m;++j){
				if(x[i][j]==1)
					s++;
			}
		}
		printf("Case #%d:\n",++cnt);  
        printf("%d\n",s);  
	}
	return 0;  
}  

你可能感兴趣的:(【百度之星初赛2】棋盘占领(深搜|广搜))