题意:给你n*m的矩阵"#"代表草“.”代表空地,问两个人同时烧草,最小需要多少时间把草烧完(燃烧的草会蔓延到它的相邻的草)
思路:算出每颗草烧到所有草所需的时间,即ma[i][k][l];
从所有的草枚举两个i,j算出它烧完所需的时间;
在加一些初始判断优化下
#include<cstdio> #include<stdlib.h> #include<string.h> #include<string> //#include<map> #include<cmath> #include<iostream> #include <queue> #include <stack> #include<algorithm> #include<set> using namespace std; #define INF 1e8 #define inf -0x3f3f3f3f #define eps 1e-8 #define ll __int64 #define maxn 250001 #define mol 100007 char mat[11][11]; int dx[4]={-1,0,0,1},k; int dy[4]={0,1,-1,0}; int n,m; int ma[110][11][11];//ma[i][k][l]表示第i棵草烧到(k,l)点草所需的时间 int vis[11][11]; struct point { int x,y,t; }p[110][110]; bool pd(int x,int y) { if(x>=0&&x<n&&y>=0&&y<m&&mat[x][y]=='#') return true; return false; } void bfss(int x,int y,int id) { queue<point>T; point a,b; ma[id][x][y]=1; a.x=x;a.y=y;a.t=1; T.push(a); p[id][k].x=x;p[id][k].y=y; while(!T.empty ()) { a=T.front (); T.pop(); for(int i=0;i<4;i++) { int xx=a.x+dx[i]; int yy=a.y+dy[i]; if(pd(xx,yy)&&!ma[id][xx][yy]) { ma[id][xx][yy]=a.t+1; b.x=xx;b.y=yy;b.t=a.t+1; T.push(b); } } } } void bfs(int x,int y) { queue<point>T; point a,b; a.x=x;a.y=y; T.push(a); vis[x][y]=1; while(!T.empty ()) { a=T.front (); T.pop(); for(int i=0;i<4;i++) { int xx=a.x+dx[i]; int yy=a.y+dy[i]; if(pd(xx,yy)&&vis[xx][yy]==0) { vis[xx][yy]=1; b.x=xx;b.y=yy; T.push(b); } } } } int main() { int t,Case=1,i,j; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); for(i=0;i<n;i++) scanf("%s",mat[i]); memset(ma,0,sizeof(ma)); memset(vis,0,sizeof(vis)); int num=0,k,l; int tmp=0; for(i=0;i<n;i++) { for(j=0;j<m;j++) { if(mat[i][j]=='#') { bfss(i,j,num++); if(vis[i][j]==0) { tmp++; bfs(i,j); } } } } printf("Case %d: ",Case++); if(num<=2)//草的数量<=2 { printf("0\n"); continue; } if(tmp>2) //草的分块>2 { printf("-1\n"); continue; } int dis=0,ans=INF,flag=0; for(i=0;i<num;i++)//枚举i,j两点开始烧 { for(j=i;j<num;j++) { dis=0;flag=0; for(k=0;k<n;k++) { for(l=0;l<m;l++) { if(mat[k][l]=='#') { if(ma[i][k][l]==0&&ma[j][k][l]==0)//关键:当i,j两点有烧不到的草,则说明i,j不行 { flag=1; break; } else if(ma[i][k][l]&&ma[j][k][l])//如果i,j两点都可以烧到(k,l)点的草则肯定t小的先烧到 { int d=ma[i][k][l]>ma[j][k][l]?ma[j][k][l]:ma[i][k][l]; if(d>dis) dis=d; } else//最晚烧完的才算全部烧完 { dis=max(ma[i][k][l],max(dis,ma[j][k][l])); } } } if(flag) break; } if(!flag&&dis<ans) { ans=dis; } } } printf("%d\n",ans-1); } return 0; }