2019 GDUT RC 1 Problem C(题解)

原题

Problem 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

题目大意

这道题是讲给一个图,然后图里面数字的大小为这个物品的颜色种类,数字为0代表该位置是空的,相邻的同色物品可以构成连通块.题目有给一个k,让你检查这个图里每个连通块的大小,如果大于等于k则把这个连通块消除(使该连通块里的所有物品的颜色种类均为0),消除之后剩余的物品还会随重力下落,如此重复直至图不存在连通块大小大于等于k,再输出这个图.

题目解析

用一个char的二维数组存题目给出的图,然后扫一遍图,如果检测到不为0的位置就dfs一次.dfs要用一个变量来记录dfs的步数,用来判定是否需要消除.dfs扫过的点也要用一个队列存起来,如果步数大于等于k,则把存起来的点全都赋值为0,否则清空队列.接着再写一个重力函数来更新重力作用后的图,如此重复知道图不能更新为止,再输出该图.关于重力函数的实现方法有多种,这里我感觉我写得很丑,仅供参考.

代码

 

  1 #include <cstdio>
  2 #include <cmath>
  3 #include <iostream>
  4 #include <cstring>
  5 #include <algorithm>
  6 #include <vector>
  7 #include <string>
  8 #include <utility>
  9 #include <queue>
 10 #include <stack>
 11 const int INF=0x3f3f3f3f;
 12 using namespace std;
 13 
 14 typedef pair<int,int> P;
 15 int dx[4]={1,-1,0,0},dy[4]={0,0,1,-1}; //dfs前进方向 
 16 char map[100][10]; //存图 
 17 int scan[100][10]; //标记dfs走过的位置(没走过为0,走过为1)
 18 int n,k;
 19 queue<P> que; //存dfs走过的点 
 20 
 21 void clear(queue<P>& q) //清空队列 
 22 {
 23     queue<P> empty;
 24     swap(empty,q);
 25  } 
 26  
 27 int dfs(int x,int y,int c) //c用来记录步数 
 28 {
 29     scan[x][y]=1;
 30     que.push(P(x,y));
 31     c++;
 32     for(int i=0;i<4;i++)
 33     {
 34     
 35         int nx,ny;
 36         nx=x+dx[i],ny=y+dy[i];
 37         if(nx>=0&&nx<n&&ny>=0&&ny<10&&!scan[nx][ny]&&(map[nx][ny]==map[x][y])) c=dfs(nx,ny,c);
 38     }
 39     return c;
 40 }
 41 
 42 void update() //重力函数 
 43 {
 44     int t;
 45     for(int j=0;j<10;j++) //从第一列底部开始往上更新 
 46     {
 47         t=0;
 48         for(int i=n-1;i>=0;i--)
 49         {
 50             if(map[i][j]=='0') t++;
 51             else
 52             {
 53             
 54                 if(t)
 55                 {
 56                 while(i>=0&&map[i][j]!='0') map[i+t][j]=map[i][j],map[i][j]='0',i--;
 57                 i=i+t+1,t=0;
 58             
 59                 }
 60             } 
 61         }
 62     }
 63     
 64 }
 65 
 66 int main()
 67 {
 68     int c,s; //s用来记录图有没有被更新过 
 69     cin>>n>>k;
 70     getchar();
 71     for(int i=0;i<n;i++)
 72     {
 73     for(int j=0;j<10;j++)
 74     scanf("%c",&map[i][j]);
 75     getchar();
 76     }
 77     while(1) //如果不能更新了会跳出该循环 
 78     {
 79     s=0;
 80     for(int i=0;i<n;i++)
 81     for(int j=0;j<10;j++)
 82     if(map[i][j]!='0')
 83     {
 84         c=dfs(i,j,0);
 85     
 86         if(c>=k)
 87         {
 88             while(que.size())
 89             {
 90             P p=que.front();que.pop();
 91             map[p.first][p.second]='0';
 92             }
 93             s++;
 94         }
 95         else clear(que);
 96     }
 97     if(!s) break;
 98     update();
 99     memset(scan,0,sizeof(scan)); //每次更新过后,不要忘记初始化 
100     }
101     
102     for(int i=0;i<n;i++)
103     {
104     for(int j=0;j<10;j++)
105     cout<<map[i][j];
106     cout<<endl;
107     }
108     return 0;
109 } 

 

 

 

 

 

 

 

转载于:https://www.cnblogs.com/VBEL/p/10394832.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值