SPOJ - AMR11J ——(BFS)
The wizards and witches of Hogwarts School of Witchcraft found Prof. Binn's History of Magic lesson to be no less boring than you found your own history classes. Recently Binns has been droning on about Goblin wars, and which goblin civilization fought which group of centaurs where etc etc. The students of Hogwarts decided to use the new-fangled computer to figure out the outcome of all these wars instead of memorizing the results for their upcoming exams. Can you help them?
The magical world looks like a 2-D R*C grid. Initially there are many civilizations, each civilization occupying exactly one cell. A civilization is denoted by a lowercase letter in the grid. There are also certain cells that are uninhabitable (swamps, mountains, sinkholes etc.) - these cells are denoted by a '#' in the grid. All the other cells - to which the civilizations can move - are represented by a '.' in the grid.
A cell is said to be adjacent to another cell if they share the same edge - in other words, for a cell (x,y), cells (x-1, y), (x, y-1), (x+1, y), (x, y+1) are adjacent, provided they are within the boundaries of the grid. Every year each civilization will expand to all unoccupied adjacent cells. If it is already inhabited by some other civilization, it just leaves the cell alone. It is possible that two or more civilizations may move into an unoccupied cell at the same time - this will lead to a battle between the civilizations and the cell will be marked with a '*'. Note that the civilizations fighting in a particular cell do not try to expand from that cell, but will continue to expand from other cells, if possible.
Given the initial grid, output the final state of the grid after no further expansion by any civilization is possible.
Input (STDIN):
The first line contains T, the number of cases. This is followed by T test case blocks.
Each test case contains two integers, R, C.
This is followed by R lines containing a string of length C. The j-th letter in the i-th row describes the state of the cell in year 0.
Each cell is either a
1. '.' which represents an unoccupied cell
2. '#' which represents a cell that cannot be occupied
3. A civilization represented by a lowercase letter ('a' - 'z')
Output (STDOUT):
For each test case, print the final grid after no expansion is possible. Apart from the notations used in the input, use '*' to denote that a battle is being waged in that particular cell.
Print a blank line at the end of each case.
Constraints:
1 <= R, C <= 500
1 <= T <= 5
Sample Input:
5
3 5
#####
a...b
#####
3 4
####
a..b
####
3 3
#c#
a.b
#d#
3 3
#c#
...
a.b
3 5
.....
.#.#.
a...b
Sample Output:
#####
aa*bb
#####
####
aabb
####
#c#
a*b
#d#
#c#
acb
a*b
aa*bb
a#.#b
aa*bb
题意:给出了你一个n*n的字符矩阵,由小写字母,‘#’,'.' 组成,小写字母表示国家,‘.’表示未占领地区,‘#’表示不能到达的地区,每一个单位时间内,国家会向它的上下左右四个方向扩张,如果到达的点是‘.’,那这个国家就可以占领这个点,并将它的名字改为自己,如果多个国家同时到达一个点,那这个点就会变成‘ * ’。输出矩阵最终的样子。
思路:这题可以用BFS来做,用队列来模拟每个单位时间所有国家扩张的情况。
将所有可以扩张的点依次压入队列。
在BFS中,同一时间的操作在队列中是靠在一起的,所以可以看成同时进行,当然,还需要用一个visit数组记录下这个元素是第几步操作的结果。
如果你要扩张到的点是‘.’,那代表你可以直接占领它,并将他的visit值在你的基础上加1。
如果你要占领的点已经被占领,但是他的visit值比你大1,表示他是其他点在和你同一步操作时的产物,那你也可以向他扩张,他将变成‘*’;
其余的情况都是不能扩张的。
并且在每个元素出队时,还要判断它是不是‘*’,因为有国家占领一个‘.’时,那这个点就会被直接入队,但它入队后,如果有其他的点也扩张到了它,那它就会在队列中变成‘*’,而‘*’是不会扩张的。
代码:
1 #include<iostream> 2 #include<cstdlib> 3 #include<cstring> 4 #include<cstdio> 5 #include<string> 6 #include<cmath> 7 #include<algorithm> 8 #include<stack> 9 #include<queue> 10 #define ll long long 11 #define inf 0x3f3f3f3f 12 #define pi 3.141592653589793238462643383279 13 using namespace std; 14 struct node{ 15 int x,y; 16 char country; 17 }map[505][505]; 18 19 int dir[4][2] = {{1,0},{0,1},{-1,0},{0,-1}}; //表示扩张的四个方向 20 int t,n,m,visit[505][505]; //visit表示这点是第几步操作的产物 21 queue<node> q; 22 23 void BFS() 24 { 25 node p,t; 26 while(!q.empty()) 27 { 28 t = q.front(); //取出队列首元素 29 q.pop(); 30 if(map[t.x][t.y].country != '*') //如果元素不是多个国家同时占领则可以扩张 31 { 32 for(int i=0; i<4; ++i) 33 { 34 p.x = t.x + dir[i][0]; 35 p.y = t.y + dir[i][1]; 36 if(p.x>=0 && p.x<n && p.y>=0 && p.y<m && map[p.x][p.y].country != '#') //如果未超出范围且不为无法到达的区域 37 { 38 if(map[p.x][p.y].country == '.') //如果是‘.’表示可以直接占领 39 { 40 map[p.x][p.y].country = map[t.x][t.y].country; //将占领的点更新为自己的名字 41 visit[p.x][p.y] = visit[t.x][t.y] + 1; //记录下这个点是第几步的操作 42 q.push(map[p.x][p.y]); //入队 43 } 44 else if(visit[p.x][p.y] == visit[t.x][t.y] + 1 && map[p.x][p.y].country != map[t.x][t.y].country) 45 //如果这个点已经被其他国家占领但是是在与自己同一步操做中占领的,则变为‘*’ 46 { 47 map[p.x][p.y].country = '*'; 48 } 49 } 50 } 51 } 52 } 53 } 54 55 int main() 56 { 57 cin>>t; 58 while(t--) 59 { 60 memset(visit,0,sizeof(visit)); 61 cin>>n>>m; 62 for(int i=0; i<n; ++i) 63 { 64 getchar(); 65 for(int j=0; j<m; ++j) 66 { 67 scanf("%c",&map[i][j].country); 68 map[i][j].x = i; 69 map[i][j].y = j; 70 if(map[i][j].country >= 'a' && map[i][j].country <= 'z') //将国家压入队列 71 { 72 visit[i][j] = 1; 73 q.push(map[i][j]); 74 } 75 } 76 } 77 BFS(); 78 for(int i=0; i<n; ++i) 79 { 80 for(int j=0; j<m; ++j) 81 cout<<map[i][j].country; 82 cout<<endl; 83 } 84 } 85 return 0; 86 } 87 /* 88 5 89 3 5 90 ##### 91 a...b 92 ##### 93 3 4 94 #### 95 a..b 96 #### 97 3 3 98 #c# 99 a.b 100 #d# 101 3 3 102 #c# 103 ... 104 a.b 105 3 5 106 ..... 107 .#.#. 108 a...b 109 */ 110