FZu2150FireGame

题意:

题意:给出一个m*n的图,‘#’表示草坪,‘ . ’表示空地,然后可以选择在任意的两个草坪格子点火,火每 1 s会向周围四个格子扩散,问选择那两个点使得燃烧所有的草坪花费时间最小?

思路: 暴力搜索

首先判断有几个连通块,如果超过2个,则无解。否则,枚举两个的初始位置,bfs后取最小值。
小优化:把在一个连通块的点放一块,这样如果有2个连通块,这两个初始点必然分布在这两个不同的连通块里,省去了无用的枚举。

// 650ms

#include <cstdio>
#include <queue>
#include <vector>
#include <cstring>
#include <algorithm>
#define fi first 
#define se second 
#define pii pair<int,int>
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const int maxn = 15;
int move[4][2] = {{0,1}, {1,0}, {0,-1}, {-1,0}};
char G[maxn][maxn];
int vis[maxn][maxn];
int d[maxn][maxn];
int n,m,ans;

// 求联通快 
void dfs(int x, int y){
	vis[x][y] = 1;
	for(int i = 0; i < 4; ++i){
		int x2 = x + move[i][0];
		int y2 = y + move[i][1];
		if(x2 >= 0&&x2 < n&&y2 >= 0&&y2 < m&&G[x2][y2] == '#'&&!vis[x2][y2]){
			dfs(x2, y2);
		}
	}
}

struct Node{
	int x, y, step;
	Node(int a = 0, int b = 0, int c = 0):x(a),y(b),step(c){}
};

void bfs(int x1, int y1, int x2, int y2){
	
	memset(vis, 0, sizeof(vis));
	memset(d, INF, sizeof(d));
	vis[x1][y1] = vis[x2][y2] = 1;
	queue<Node> Q;
	Q.push(Node(x1,y1,1));
	if(x1 != x2 || y1 != y2) Q.push(Node(x2,y2,1));
	Node next;
	while(!Q.empty()){
		Node t = Q.front(); Q.pop();
		d[t.x][t.y] = min(d[t.x][t.y], t.step);
		for(int i = 0; i < 4; ++i){
			next.x = t.x + move[i][0];
			next.y = t.y + move[i][1];
			if(next.x >= 0&&next.x < n&&next.y >= 0&&next.y < m&&G[next.x][next.y] == '#'&&vis[next.x][next.y] == 0){
				vis[next.x][next.y] = 1;
				next.step = t.step + 1;
				Q.push(next);
			}
		}
	}
}

void find_ans(){
	int t = 0;
	for(int i = 0; i < n; ++i){
		for(int j = 0; j < m; ++j){
			if(G[i][j] == '#')
			t = max(t, d[i][j]-1); 
		} 
	}
	ans = min(ans, t);
}

int main()
{
	freopen("in.txt","r",stdin);
	int T; scanf("%d",&T);
	int kase = 1;
	while(T--){
		scanf("%d %d",&n,&m); 
		printf("Case %d: ",kase++);
		for(int i = 0; i < n; ++i){
			scanf("%s",G[i]);	
		}
		
		memset(vis, 0, sizeof(vis));
		int cnt = 0; // 联通快 
		bool flag = true;
		
		for(int i = 0; i < n; ++i){
			for(int j = 0; j < m; ++j){
				if(G[i][j] == '#'&&!vis[i][j]){
					++cnt;
					if(cnt > 2) { flag = false; break; }
					dfs(i, j);
				}	
			}
			if(!flag) break;
		}
		//printf("blocks %d ",cnt);
		if(!flag) printf("-1\n");
		else{
			ans = INF;
			for(int x1 = 0; x1 < n; ++x1)
			for(int y1 = 0; y1 < m; ++y1)
			for(int x2 = 0; x2 < n; ++x2)
			for(int y2 = 0; y2 < m; ++y2){
				if(G[x1][y1] == '#'&&G[x2][y2] == '#'){
					bfs(x1,y1,x2,y2);
					//printf("%d %d -> %d %d, = %d \n",x1,y1,x2,y2,t);
					//finalans = min(finalans, t);
					find_ans();
				}
			}
			printf("%d\n", ans);
		}
	}

	return 0;
}

加小优化后,(数据量小,优势不明显):

//500ms

#include <cstdio>
#include <queue>
#include <vector>
#include <cstring>
#include <algorithm>
#define fi first 
#define se second 
#define pii pair<int,int>
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const int maxn = 15;
int move[4][2] = {{0,1}, {1,0}, {0,-1}, {-1,0}};
char G[maxn][maxn];
int vis[maxn][maxn];
int d[maxn][maxn];
vector<pii> blocks[3];
int n,m,ans;

// 求联通快 
void dfs(int x, int y, int c){
	vis[x][y] = 1;
	blocks[c].push_back( make_pair(x,y) );
	for(int i = 0; i < 4; ++i){
		int x2 = x + move[i][0];
		int y2 = y + move[i][1];
		if(x2 >= 0&&x2 < n&&y2 >= 0&&y2 < m&&G[x2][y2] == '#'&&!vis[x2][y2]){
			dfs(x2, y2, c);
		}
	}
}

struct Node{
	int x, y, step;
	Node(int a = 0, int b = 0, int c = 0):x(a),y(b),step(c){}
};

int bfs(int x1, int y1, int x2, int y2){
	
	memset(vis, 0, sizeof(vis));
	memset(d, INF, sizeof(d));
	vis[x1][y1] = vis[x2][y2] = 1;
	queue<Node> Q;
	Q.push(Node(x1,y1,1));
	if(x1 != x2 || y1 != y2) Q.push(Node(x2,y2,1));
	Node next;
	int maxd = 0;
	while(!Q.empty()){
		Node t = Q.front(); Q.pop();
		d[t.x][t.y] = min(d[t.x][t.y], t.step);
		for(int i = 0; i < 4; ++i){
			next.x = t.x + move[i][0];
			next.y = t.y + move[i][1];
			if(next.x >= 0&&next.x < n&&next.y >= 0&&next.y < m&&G[next.x][next.y] == '#'&&vis[next.x][next.y] == 0){
				vis[next.x][next.y] = 1;
				next.step = t.step + 1;
				maxd = max(maxd, next.step-1);
				Q.push(next);
			}
		}
	}
	return maxd;
}

int main()
{
	freopen("in.txt","r",stdin);
	int T; scanf("%d",&T);
	int kase = 1;
	while(T--){
		scanf("%d %d",&n,&m); 
		printf("Case %d: ",kase++);
		for(int i = 0; i < n; ++i){
			scanf("%s",G[i]);	
		}
		
		memset(vis, 0, sizeof(vis));
		blocks[1].clear(); blocks[2].clear();
		int cnt = 0; // 联通快 
		bool flag = true;
		
		for(int i = 0; i < n; ++i){
			for(int j = 0; j < m; ++j){
				if(G[i][j] == '#'&&!vis[i][j]){
					++cnt;
					if(cnt > 2) { flag = false; break; }
					dfs(i, j, cnt);
				}	
			}
			if(!flag) break;
		}
		//printf("blocks %d ",cnt);
		if(!flag) printf("-1\n");
		else{
			int s1,s2; //连通块编号 
			if(cnt == 1){
				s1 = s2 = 1;
			}
			else{
				s1 = 1; s2 = 2;
			}
			ans = INF;
			for(vector<pii>::iterator it = blocks[s1].begin(); it != blocks[s1].end(); ++it){
				for(vector<pii>::iterator it2 = blocks[s2].begin(); it2 != blocks[s2].end(); ++it2){
					int x1 = it->fi, y1 = it->se;
					int x2 = it2->fi, y2 = it2->se;
					int t = bfs(x1, y1, x2, y2);
					ans = min(ans, t);
				}
			}
			printf("%d\n",ans);
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/CY05627/article/details/89478747