• 2019 GDUT Rating Contest I : Problem C. Mooyo Mooyo


    题面:

    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 }
     
     
  • 相关阅读:
    JAVA设计模式之策略模式
    Outlook邮箱配置
    Linux命令
    开发工具使用技巧
    java连接VMware虚拟机Oracle数据库问题
    C#创建带有界面交互的windows服务
    Google Galaxy Nexus刷系统
    业务逻辑?到底是什么
    发明轮子
    IBM服务器机组初始设置
  • 原文地址:https://www.cnblogs.com/happy-MEdge/p/10400785.html
Copyright © 2020-2023  润新知