usaco
USACO SILVER::2018 December - Mooyo Mooyo
USACO SILVER
USACO SILVER::2018 December - Mooyo Mooyo
Mooyo Mooyo
- level : Gold 4
- tag : bfs, graph theory, impelentation
- BOJ에 존재하는 Puyo Puyo라는 문제와 거의 유사한 문제입니다.
Point
- n과 k가 주어집니다.
- n * 10 인 배열이 주어집니다.
- 이 배열에는 [0:9] 범위 중 하나의 숫자가 적혀있습니다.
- 0은 빈칸을 의미하고,
- 나머지 숫자는 각 블록의 색을 의미합니다.
- 주어진 배열을 토대로 시뮬레이션을 진행하고, 더 이상 폭발하지 않는 격자의 최종 상태를 출력합니다.
- 격자에 있는 숫자들은 adjacent 한 위치에 있는 숫자와 같은 숫자를 가지는 경우 하나의 그룹이라고 합시다.
- 해당 그룹의 그룹원의 수가 k이상인 경우 해당 그룹원 전부는 폭발하여 값이 0으로 바뀌게 됩니다.
- 또한 이러한 과정은 동시에 진행됩니다.
- 폭발이 동시에 진행된 이후, 공중에 떠있는 블록들은 중력의 영향을 받습니다.
- 중력은 각 열방향별로 독자적으로 작용합니다.
Design(x)
- 기존 Puyo Puyo와 동일합니다.
- 폭발이 일어나지 않을때까지 아래 과정을 반복합니다.
- 먼저, bfs를 통해 인접하고 같은 숫자를 가지는 그룹의 수를 세고, k개 이상인 경우 폭발시킵니다.
- 이후, 이중 for문을 통해 블록에 중력을 작용시킵니다.
Big O(time)
- O(N^2)
Big O(memory)
Code(x)
#include<bits/stdc++.h>
#define endl '\n'
#define rep(i,a,b) for(int i=a;i<b;i++)
#define r_rep(i,a,b) for(int i=a;i>b;i--)
const int MAXN = 100+1, MAXM = 10+1;
const int dx[]={-1, 0, 1, 0}, dy[]={0, 1, 0, -1};
using namespace std;
int n, m, mxk;
int a[MAXN][MAXM];
bool visited[MAXN][MAXM];
queue<pair<int,int> > q, bq;
bool over(int x, int y){ return (x<0 || y<0 || x>=n || y>=m);}
void bfs(bool& nothing, const int sx, const int sy, const int colur){
while(!q.empty()) q.pop();
while(!bq.empty()) bq.pop();
visited[sx][sy] = true;
q.push({sx, sy});
bq.push({sx, sy});
while(!q.empty()){
int x = q.front().first, y = q.front().second; q.pop();
rep(i, 0, 4){
int nx = x+dx[i], ny = y+dy[i];
if(over(nx, ny) || visited[nx][ny] || a[nx][ny] != colur) continue;
visited[nx][ny] = true;
q.push({nx, ny});
bq.push({nx, ny});
}
}
if(bq.size() >= mxk){
nothing = false;
while(!bq.empty()){
int x = bq.front().first, y = bq.front().second; bq.pop();
a[x][y] = 0;
}
}
}
void PRINT(){
rep(i, 0, n){
rep(j, 0, m){
cout << a[i][j];
}cout << endl;
}
}
void gravity(){
int b[MAXN][MAXM]={0};
rep(j, 0, m){
int idx = n-1;
r_rep(i, n-1, -1){
if(a[i][j] != 0){
b[idx--][j] = a[i][j];
}
}
}
memcpy(a, b, sizeof(b));
}
void solve(){
bool NOTHING;
while(true){
NOTHING = true;
memset(visited, false, sizeof(visited));
// bfs
rep(i, 0, n){
rep(j, 0, m){
if(visited[i][j] == false && a[i][j] != 0){
bfs(NOTHING, i, j, a[i][j]);
}
}
}
if(NOTHING) break;
// gravity
gravity();
}
}
int main(){
//freopen("input.txt", "r", stdin);
m = 10;
scanf("%d %d",&n,&mxk);
rep(i, 0, n) rep(j, 0, m) scanf("%1d",&a[i][j]);
solve();
PRINT();
return 0;
}