题目大意:有一个矩阵,"."表示石头,"#",表示小草,有两个人,可以在任意两个位置点燃小草,小草可以上下左右蔓延,蔓延一次的时间为1,问所有蔓延完所有小草所花费的最短时间。如果不可能蔓延完所有的小草,输出-1。
题解:暴力枚举两个点的位置,然后以这两个点为起点,将这两个点放入队列中,跑bfs。(属于多起点bfs问题)
code:
#include<cstdio> #include<iostream> #include<cstring> #include<queue> using namespace std; const int INF=1e9+7; const int N = 20; char mp[N][N]; struct stu { int x, y, time; }; int n, m; int sum=INF; int d[4][2]={1,0,0,1,0,-1,-1,0}; bool mark[N][N]; queue<stu> que; int bfs(){ int ans=0; while(que.size()){ stu x1=que.front(); que.pop(); ans=max(ans,x1.time); for(int i=0;i<4;i++){ int dx=x1.x+d[i][0]; int dy=x1.y+d[i][1]; if(dx<1||dy<1||dx>n||dy>m||mp[dx][dy]=='.'||mark[dx][dy]) continue ; stu c; c.x=dx;c.y=dy;c.time=1+x1.time;que.push(c); mark[dx][dy]=1; } } for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ if(mp[i][j]=='#'&&mark[i][j]==0) return INF; } } return ans; } void solve(int time){ sum=INF; bool flag=0; cin >> n >> m; for (int i = 1; i <= n; i++) scanf("%s", mp[i] + 1); for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { for (int k = 1; k <= n; k++) { for (int k1 = 1; k1 <= m; k1++) { if(i==k&&j==k1) continue ; if (mp[i][j] == '.' || mp[k][k1] == '.')continue; else { flag=1; memset(mark, 0, sizeof mark); stu c; c.x=i;c.y=j;c.time=0;que.push(c); c.x=k;c.y=k1;c.time=0;que.push(c); mark[i][j]=1;mark[k][k1]=1; sum=min(bfs(),sum); } } } } } if(!flag) sum=0; printf("Case %d: %d\n",time,sum==INF? -1:sum); } int main(){ int t; cin >> t; for(int i=1;i<=t;i++) solve(i); return 0; }