题面:
C. Mooyo Mooyo
Input file: standard input
Output file: standard output
Time limit: 1 second
Memory limit: 256 megabytes
With plenty of free time on their hands (or rather, hooves), the cows on Farmer John’s farm often pass the time by playing video games. One of their favorites is based on a popular human video game called Puyo Puyo; the cow version is of course called Mooyo Mooyo. The game of Mooyo Mooyo is played on a tall narrow grid N cells tall (1 ≤ N ≤ 100) and 10 cells wide. Here is an example with N = 6:
0000000000
0000000300
0054000300
1054502230
2211122220
1111111223
Each cell is either empty (indicated by a 0), or a haybale in one of nine different colors (indicated by characters 1..9). Gravity causes haybales to fall downward, so there is never a 0 cell below a haybale.
Two cells belong to the same connected region if they are directly adjacent either horizontally or vertically, and they have the same nonzero color. Any time a connected region exists with at least K cells, its haybales all disappear, turning into zeros. If multiple such connected regions exist at the same time, they all disappear simultaneously. Afterwards, gravity might cause haybales to fall downward to fill some of the resulting cells that became zeros. In the resulting configuration, there may again be connected regions of size at least K cells. If so, they also disappear (simultaneously, if there are multiple such regions), then gravity pulls the remaining cells downward, and the process repeats until no connected regions of size at least K exist.
Given the state of a Mooyo Mooyo board, please output a final picture of the board after these operations have occurred.
Input
The first line of input contains N and K(1 ≤ K ≤ 10N). The remaining N lines specify the initial state of the board.
Output
Please output N lines, describing a picture of the final board state.
Example
Input
6 3
0000000000
0000000300
0054000300
1054502230
2211122220
1111111223
Output
0000000000
0000000000
0000000000
0000000000
1054000000
2254500000
Note
In the example above, if K=3, then there is a connected region of size at least K with color 1 and also one with color 2. Once these are simultaneously removed, the board temporarily looks like this:
0000000000
0000000300
0054000300
1054500030
2200000000
0000000003
Then, gravity takes effect and the haybales drop to this configuration:
0000000000
0000000000
0000000000
0000000000
1054000300
2254500333
Again, there is a region of size at least K (with color 3). Removing it yields the final board configuration:
0000000000
0000000000
0000000000
0000000000
1054000000
2254500000
题目描述:
农夫在玩一个游戏,这个游戏是:给出一个图,如果有相同相连(上下左右,不包括对角)的数字的数量大于等于K,那么它们就消除掉(变为数字0),直到不能消掉为止。消掉后要遵守“重力下落”的规则:如果一个非零的数字下方为0,那么它就会“掉下去”,直到下方数字不为0;
题目分析:
这道题就是用dfs解决图的连通块问题,怎样解决连通的数字超过K个时就消掉?我们可以分别写两个dfs,一个dfs是检测连通的数字是否大于等于K,另一个dfs就是清空操作。在写第一个dfs时,用一个vis数组来检查是否被访问过就可以避免重复计算连通的数字。另一个dfs要注意清空时还能保留要清空的数字,我是通过传入要清空的数字来实现的,这个做法因人而异。最后一个“重力下落”的函数最好从下到上“重力下落”,这样能保证每一次“重力下落”都是下落到最底端。
AC代码:
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <cmath> 5 #include <algorithm> 6 using namespace std; 7 int n, k; 8 char s[105][15]; 9 int vis[105][15]; //记录点是否被访问过 10 int dr[4] = {-1, 1, 0, 0}, dc[4] = {0, 0, -1, 1}; //方向:上下左右 11 int cnt; //记录连通的数字 12 13 void down(){ //重力下落 14 for(int i = n-1; i >= 1; i--){ 15 for(int j = 0; j < 10; j++){ 16 for(int k = i; k < n && s[k][j] == '0'; k++){ 17 s[k][j] = s[k-1][j]; 18 s[k-1][j] = '0'; 19 } 20 } 21 } 22 } 23 24 int check(int r, int c){ //检查函数 25 if(r < 0 || r >= n || c < 0 || c >= 10) return 0; 26 if(vis[r][c]) return 0; 27 return 1; 28 } 29 30 void dfs(int r, int c){ 31 32 vis[r][c] = 1; //每到一个点就标记一下 33 cnt++; 34 for(int i = 0; i < 4; i++){ 35 int R = r+dr[i], C = c+dc[i]; 36 if(check(R, C) && s[R][C] == s[r][c]){ 37 dfs(R, C); 38 } 39 } 40 } 41 42 void clear_num(int r, int c, int ch){ //清空操作 43 s[r][c] = '0'; 44 for(int i = 0; i < 4; i++){ 45 int R = r+dr[i], C = c+dc[i]; 46 if( (r >= 0 && r < n && c >= 0 && c < 10) && s[R][C] == ch){ 47 clear_num(R, C, ch); 48 } 49 } 50 51 } 52 53 54 int main(){ 55 cin >> n >> k; 56 for(int i = 0; i < n; i++) cin >> s[i]; 57 58 while(1){ 59 60 memset(vis, 0, sizeof(vis)); //清空vis数组 61 62 int flag = 1; //是否有大于等于K的连通数字的标志 63 for(int i = 0; i < n; i++){ 64 for(int j = 0; j < 10; j++){ 65 if(s[i][j] != '0') { 66 cnt = 0; 67 dfs(i, j); 68 if(cnt >= k) { 69 flag = 0; 70 clear_num(i, j, s[i][j]); 71 } 72 } 73 } 74 } 75 76 down(); 77 78 if(flag) break; //没有大于等于K的连通块,结束 79 80 81 } 82 83 for(int i = 0; i < n; i++){ 84 for(int j = 0; j < 10; j++){ 85 cout << s[i][j]; 86 } 87 cout << endl; 88 } 89 90 return 0; 91 }