2015 百度之星 初赛2 1003 棋盘占领 (bfs)题解



百小度最近迷恋上了一款游戏,游戏里有一个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:

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


思路显然就是bfs,每次入队新的被占领的城池

代码如下

#include<cstdio>  
#include<cstring>  
#include<cmath>  
#include<cstdlib>  
#include<iostream>  
#include<algorithm>  
#include<vector>  
#include<map>  
#include<queue>  
#include<stack> 
#include<string>
#include<map> 
using namespace std;  
#define LL long long  
//const int maxn=100005;
//const int INF=1000000000;


int G[505][505];
//set<pair<int,int> > zhanling;
queue<pair<int, int> > q; 
const int dx[] = {-1, 1, 1, -1};
const int dy[] = {-1, -1, 1, 1};
const int dtx[] = {0, 1, 0, -1};
const int dty[] = {-1, 0, 1, 0};

int main(){
//	freopen("input.txt", "r", stdin);
	int t, kase = 0; scanf("%d", &t);
	while(t--){
//		zhanling.clear();
		memset(G, 0, sizeof(G));
		
		int n, m;	scanf("%d%d", &n, &m);
		int g; scanf("%d", &g);
		int ans = 0;
		for(int i = 0; i < g; i++) {
			int u, v; scanf("%d%d", &u, &v);
			//zhanling.insert(make_pair(u, v));
			if(G[u][v]) continue;
			q.push(make_pair(u, v));
			G[u][v] = 1;
			ans ++;
		} 
		
		while(!q.empty()) {
			pair<int, int> tmp = q.front(); q.pop();
			int u = tmp.first, v = tmp.second;
			for(int i = 0; i < 4; i++) {
				if(u + dx[i] <= 0 || u + dx[i] > n || v + dy[i] <= 0 || v + dy[i] > m || !G[u + dx[i]][v + dy[i]])
					continue;
				if(!G[u + dtx[i]][v+dty[i]]) {
					q.push(make_pair(u + dtx[i], v+dty[i]));
					G[u + dtx[i]][v+dty[i]] = 1;
					ans++;
				}
				if(!G[u + dtx[(i+3) % 4]][v+dty[(i+3) % 4]]) {
					q.push(make_pair(u + dtx[(i+3)%4], v+dty[(i+3)%4]));
					G[u + dtx[(i+3)%4]][v+dty[(i+3)%4]] = 1;
					ans++;
				}
			}
		}
		
		printf("Case #%d:\n", ++kase);
		printf("%d\n", ans);
	}

}  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值