題意:給你塊地,有空地,也有草堆,讓你選兩個草堆進行點火,燃燒的草堆會引燃上下左右的相鄰草堆,每一次引燃花費1s時間,問你最少花多長時間把草堆都點著,如果做不到輸出-1.
思路:每次枚舉兩塊草坪,兩端同時bfs(也就是說一開始加入兩個節點到隊列當中,和以前的類型一個道理沒什么區別),用變量count1計算草坪個數,當count1減小到0時,即找到了本次枚舉的解,并在節點node中設置一變量為c記錄當前狀態草坪個數(用于返回結果的判斷)。
AC代碼如下:
#include<cstdio>#include<queue>#include<vector> #include<cstring>#include<algorithm>using namespace std;const int maxn=10+2;struct node{ int x,y; int c; //當前狀態下草坪的剩余數量 node(int x=0,int y=0,int c=0):x(x),y(y),c(c){}}; int n,m;int count1; //草坪數量 char g[maxn][maxn]; int d[maxn][maxn];int dir[][2]={{0,1},{0,-1},{1,0},{-1,0}};bool isValid(node &nd){ return nd.x>=0&&nd.x<n && nd.y>=0&&nd.y<m;}int bfs(node &n1,node &n2){ int t=count1; //要保證每次枚舉草坪的數量不會被改變 memset(d,-1,sizeof(d)); queue<node>q; n1.c=--t; q.push(n1); n2.c=--t; q.push(n2); d[n1.x][n1.y]=0; d[n2.x][n2.y]=0; while(!q.empty()){ node u=q.front(); q.pop(); if(!u.c){ //當草坪的數量為零時說明已經燃燒完了 return d[u.x][u.y];} for(int i=0;i<4;i++){ node v=node(dir[i][0]+u.x,dir[i][1]+u.y,0); if(isValid(v) && d[v.x][v.y]==-1 && g[v.x][v.y]=='#'){ v.c=--t; q.push(v); d[v.x][v.y]=d[u.x][u.y]+1; } } } return -1;}int main(){ int T; scanf("%d",&T); int flag=0; while(T--){ scanf("%d%d",&n,&m); for(int i=0;i<n;i++)scanf("%s",g[i]); count1=0; vector<node>vec; for(int i=0;i<n;i++) for(int j=0;j<m;j++) if(g[i][j]=='#'){ vec.push_back(node(i,j,0)); count1++; } if(vec.size()>2){ int min1=10000; //當草坪數量<=2時直接輸出0,否則每次枚舉兩個草坪 for(int i=0;i<vec.size();i++){ for(int j=i+1;j<vec.size();j++){ int temp=bfs(vec[i],vec[j]); if(temp!=-1){ min1=min(min1,temp); } } } if(min1==10000)PRintf("Case %d: -1/n",++flag); else printf("Case %d: %d/n",++flag,min1); }else printf("Case %d: 0/n",++flag); } return 0;}
新聞熱點
疑難解答