题目连接:https://vjudge.net/problem/26262/origin
题目大意:部落冲突,给出一块r*c宽度的地,输入字母x(a-z)代表部落x,输入#代表山丘,部落不可以通过此地,'.'代表空地,部落可以在此处扩张土地。每个部落每年都会向周围扩张土地,被占的土地标记原部落的字母,若有两个部落同时到达一块地则两部落发生战争,被标记为'*'且发生战争的地方任何部落不能通过(战争不会延续到周围,且有战争那么战争便会一直持续),求若干年后这块地是什么样的。
思路:扩张的问题当然首选bfs。但之前学bfs时,扩张点都是从一个点开始的,所以一开始卡了很久,后来得知将原始所有的部落都压入队列中,就可以对多个点同时进行扩张(队列的性质,每次出队出队首,进队进队尾,队首到队尾正好是每个部落占据的点),同时while()里的判断多了几个。会用bfs这题就很简单了,那就随便做下笔记,记下多组数据可以同时压入队列的解题方法再记下ac代码。
代码如下:
1 #include<iostream> 2 #include<queue> 3 #include<cstring> 4 using namespace std; 5 int vis[505][505]; 6 int cc[]={1,-1,0,0},dd[]={0,0,1,-1}; 7 struct point{ 8 char a; 9 int i,j,x; 10 }p[505][505]; 11 queue<point> dui; 12 void bfs() 13 { 14 while(!dui.empty()) 15 { 16 point now; 17 now=dui.front(); 18 if(p[now.i][now.j].a=='*')//如果此地发生战争就不用扩张了 19 { 20 dui.pop(); 21 continue; 22 } 23 for(int i=0;i<4;i++) 24 if(!vis[now.i+cc[i]][now.j+dd[i]]) 25 { 26 if(p[now.i+cc[i]][now.j+dd[i]].a=='.') 27 { 28 p[now.i+cc[i]][now.j+dd[i]].a=now.a; 29 p[now.i+cc[i]][now.j+dd[i]].x=now.x+1; 30 dui.push(p[now.i+cc[i]][now.j+dd[i]]); 31 } 32 else if(now.a!=p[now.i+cc[i]][now.j+dd[i]].a&&now.x!=p[now.i+cc[i]][now.j+dd[i]].x) 33 p[now.i+cc[i]][now.j+dd[i]].a='*'; 34 } 35 dui.pop(); 36 } 37 } 38 int main() 39 { 40 int n; 41 while(cin>>n) 42 { 43 int r,c,count; 44 while(n--) 45 { 46 cin>>r>>c; 47 memset(vis,1,sizeof(vis)); 48 for(int i=0;i<=r+1;i++) 49 for(int j=0;j<=c+1;j++) 50 { 51 p[i][j].i=i; 52 p[i][j].j=j; 53 } 54 for(int i=1;i<=r;i++) 55 for(int j=1;j<=c;j++) 56 { 57 cin>>p[i][j].a; 58 if(p[i][j].a=='.') 59 vis[i][j]=0; 60 else if(p[i][j].a=='#') 61 continue; 62 else 63 { 64 p[i][j].x=0; 65 dui.push(p[i][j]); 66 } 67 } 68 bfs(); 69 for(int i=1;i<=r;i++) 70 { 71 for(int j=1;j<=c;j++) 72 cout<<p[i][j].a; 73 cout<<endl; 74 } 75 } 76 } 77 return 0; 78 }