FOJ 2150 在二维草地上点火烧完所有草最少时间 BFS+图论+容斥

题目链接:http://acm.fzu.edu.cn/problem.php?pid=2150

题意:

给定一个平面图 . 为空地(不着火) # 为草

开始可以选1-2个草堆点燃,每隔一秒会把上下左右的草引燃(开始时间为0秒)

问把所有草烧光的最少时间

给定的图中必有草

 

 思路:

纯暴力的话复杂度是 n^8 TLE

我们可以先处理出2个数组

d数组 表示任意点间距离

go[i][j] 表示 在 (i ,j) 所在的联通块 中里 (i ,j) 最远的草的距离

 

预处理时间为n^4

 

对于题目中的草其实可以分为

联通块>2 (显然是烧不完的 , ans = -1)

联通块 == 2 ( 每个联通块都要一个火把点燃, 而每个联通块最长时间则是 go[ 该联通块的点 ] , 取个两联通块需要的最长时间即可  复杂度为n^2)

联通块 == 1 ( 我们设 a, b为起点 ,则对于图中的草c,被点燃的时间就是 min(d[a][c], d[b][c]) ,则暴力一下所有草就得到 ab为起点的时间,暴力一下ab就得到正解

复杂度为n^6

 

#include<iostream>
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<algorithm>
#include<queue>
#include<set>
using namespace std;
#define N 12
int f[1000];
int find(int x){return x==f[x]?x:f[x] = find(f[x]);}
int idx(int x,int y){return x*10+y;}
void Union(int x,int y){
	int fx = find(x), fy = find(y);
	if(fx == fy)return ;
	fx<fy ? f[fy] = fx: f[fx] = fy;
}
int map[N][N], n, m;

struct node{
	int x, y;
};
int step[4][2]={0,1,1,0,0,-1,-1,0};
bool inmap(node x){return 0<=x.x && x.x<n && 0<=x.y &&x .y<m;}
int d[N][N][N][N];//任意点距离
int BFS(node a){
	d[a.x][a.y][a.x][a.y] = 0;

	queue<node>q;
	q.push(a);
	int ans = 0;
	while(!q.empty()){
		node u = q.front(); q.pop();
		for(int i = 0;i < 4; i++){
			node v = u;		v.x += step[i][0];	v.y += step[i][1];
			if(!inmap(v) || map[v.x][v.y] == 0 || d[a.x][a.y][v.x][v.y] != -1)continue;

			d[a.x][a.y][v.x][v.y] = d[a.x][a.y][u.x][u.y]+1;

			ans = max(ans, d[a.x][a.y][v.x][v.y]);
			q.push(v);
		}
	}
	return ans;
}

set<int>myset;//所有祖先
set<int>::iterator p;
int go[N][N]; //go[i][j]表示在(i,j)联通块中离(i,j)最远点距离
int main()
{
	int T,Cas = 1;
	scanf("%d",&T);
	int i, j, k, l;
	while(T--){
		myset.clear();
		memset(d, -1, sizeof(d));
		memset(go, -1, sizeof(go));
		memset(map, 0, sizeof(map));
		scanf("%d %d",&n,&m);
		for(i=0;i<N*N;i++)f[i] = i;
		int size = 0;
		for(i=0;i<n;i++)
		{ char s[20];scanf("%s",s);
		for(j=0;j<m;j++)
		{
			map[i][j] = s[j] == '#'; 
			if(map[i][j])
			{
				size++;
				for(k = 0;k<4;k++)
				{
					int x=i+step[k][0], y =j+step[k][1];
					if(x<0 || x>=n || y<0 || y>=m || map[x][y] == 0)continue;
					Union(idx(i,j), idx(x,y));
				}
			}
		}
		}
		if(size<=2){printf("Case %d: 0\n",Cas++);continue;}
		for(i= 0;i<n;i++)
			for(j=0;j<m;j++)if(map[i][j])find(idx(i,j));

		for(i= 0;i<n;i++)for(j=0;j<m;j++)if(map[i][j])
			myset.insert(f[idx(i,j)]);
		if(myset.size() >= 3){printf("Case %d: -1\n",Cas++);continue;}
		bool hehe = myset.size() == 2;

		int ans = 100000;
		for(i=0;i<n;i++)
			for(j=0;j<m;j++)if(map[i][j])
			{
				node a; a.x =i, a.y =j;
				go[i][j] =  BFS(a);
			}
			if(hehe)
			{	
				p = myset.begin();
				int f1 = *p, a1=1000000;
				p++;
				int f2 = *p, a2=1000000;
				for(i =0;i<n;i++)
					for(j=0;j<m;j++)if(map[i][j] && f[idx(i,j)] == f1)a1 = min(a1, go[i][j]);

				for(i =0;i<n;i++)
					for(j=0;j<m;j++)if(map[i][j] && f[idx(i,j)] == f2)a2 = min(a2, go[i][j]);
				ans = max(a1,a2);
			}
			else
			{
				for(i = 0; i < n; i++)
					for(j = 0; j < m; j++)if(map[i][j])
						for(k = 0; k < n; k++)
							for(l = 0; l < m; l++)if(map[k][l])
							{
								int tmp = 0;
								for(int z = 0; z < n; z++)
									for(int y = 0; y<m;y++)if(map[z][y])
										tmp = max(tmp, min(d[i][j][z][y],d[k][l][z][y]));
								ans = min(ans, tmp);
							}
			}
			printf("Case %d: %d\n", Cas++, ans);
	}
	return 0;
}
/*
99
3 3
.#.
###
.#.
3 3
.#.
#.#
.#.
3 3
...
#.#
...
3 3
###
..#
#.#

3 3
###
...
#.#

1 1
#

1 10
.#######.#

10 10
.#.#.#.#.#
.#.#.#.#.#
.#.#.#.#.#
.#.#.#.#.#
.#.#.#.#.#
.#.#.#.#.#
.#.#.#.#.#
.#.#.#.#.#
.#.#.#.#.#
.#.#.#.#.#

10 10
####.#####
####.#####
####.#####
####.#####
####.#####
####.#####
####.#####
####.#####
####.#####
####.#####
10 10
##########
##########
##########
##########
##########
##########
##########
##########
##########
##########
9 9
#########
#########
#########
#########
#########
#########
#########
#########
#########
3 3
###
###
###
4 4
####
####
####
####

5 5
#####
#####
#####
#####
#####

5 5
##.##
##.##
##.##
##.##
##.##

5 5
##.##
##..#
#.###
##.#.
##.##

6 7
#.#.#.#
#.#.#.#
###.#.#
#####..
###..##
#######

6 8
#.#.#.##
#.#.#.#.
###.#.##
#####..#
###..###
#######.

7 8
#.#.#.##
#.#.#.#.
###.#.##
#####..#
###..###
######..
......##

7 8
#.#.#.##
#.#.#.#.
###.#.##
#####..#
###...##
######..
......##

7 8
#.#.#.##
#.#.#.#.
###.####
#####..#
###...##
######..
......##

3 3
.#.
...
#.#

8 8
#.#.#.##
#.#.#.#.
###.####
#####..#
###...##
######..
......##
#######.

8 8
########
......#.
########
.#......
#.######
#.######
###.####
########

9 1
.
#
#
.
#
#
#
#
#

9 1
#
#
#
#
#
#
#
#
#

10 10
####.#####
####.#####
####.#####
##########
....#.....
####.#####
####.#####
####.#####
##########
####.#####

*/


 

 

 

 

你可能感兴趣的:(FOJ 2150 在二维草地上点火烧完所有草最少时间 BFS+图论+容斥)