https://www.acmicpc.net/problem/21609
21609번: 상어 중학교
상어 중학교의 코딩 동아리에서 게임을 만들었다. 이 게임은 크기가 N×N인 격자에서 진행되고, 초기에 격자의 모든 칸에는 블록이 하나씩 들어있고, 블록은 검은색 블록, 무지개 블록, 일반 블록
www.acmicpc.net
문제
상어 중학교의 코딩 동아리에서 게임을 만들었다. 이 게임은 크기가 N×N인 격자에서 진행되고, 초기에 격자의 모든 칸에는 블록이 하나씩 들어있고, 블록은 검은색 블록, 무지개 블록, 일반 블록이 있다. 일반 블록은 M가지 색상이 있고, 색은 M이하의 자연수로 표현한다. 검은색 블록은 -1, 무지개 블록은 0으로 표현한다. (i, j)는 격자의 i번 행, j번 열을 의미하고, |r1 - r2| + |c1 - c2| = 1을 만족하는 두 칸 (r1, c1)과 (r2, c2)를 인접한 칸이라고 한다.
블록 그룹은 연결된 블록의 집합이다. 그룹에는 일반 블록이 적어도 하나 있어야 하며, 일반 블록의 색은 모두 같아야 한다. 검은색 블록은 포함되면 안 되고, 무지개 블록은 얼마나 들어있든 상관없다. 그룹에 속한 블록의 개수는 2보다 크거나 같아야 하며, 임의의 한 블록에서 그룹에 속한 인접한 칸으로 이동해서 그룹에 속한 다른 모든 칸으로 이동할 수 있어야 한다. 블록 그룹의 기준 블록은 무지개 블록이 아닌 블록 중에서 행의 번호가 가장 작은 블록, 그러한 블록이 여러개면 열의 번호가 가장 작은 블록이다.
오늘은 이 게임에 오토 플레이 기능을 만드려고 한다. 오토 플레이는 다음과 같은 과정이 블록 그룹이 존재하는 동안 계속해서 반복되어야 한다.
- 크기가 가장 큰 블록 그룹을 찾는다. 그러한 블록 그룹이 여러 개라면 포함된 무지개 블록의 수가 가장 많은 블록 그룹, 그러한 블록도 여러개라면 기준 블록의 행이 가장 큰 것을, 그 것도 여러개이면 열이 가장 큰 것을 찾는다.
- 1에서 찾은 블록 그룹의 모든 블록을 제거한다. 블록 그룹에 포함된 블록의 수를 B라고 했을 때, B2점을 획득한다.
- 격자에 중력이 작용한다.
- 격자가 90도 반시계 방향으로 회전한다.
- 다시 격자에 중력이 작용한다.
격자에 중력이 작용하면 검은색 블록을 제외한 모든 블록이 행의 번호가 큰 칸으로 이동한다. 이동은 다른 블록이나 격자의 경계를 만나기 전까지 계속 된다.
출력
첫째 줄에 획득한 점수의 합을 출력한다.
제한
- 1 ≤ N ≤ 20
- 1 ≤ M ≤ 5
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
int N , M ,ans = 0;
int map[21][21];
int dir[4][2] = { {1,0}, {0,1}, {-1,0}, {0,-1}};
bool vist[21][21];
void zero_init(){
for(int i = 0 ; i < N ;i ++){
for(int j = 0 ; j< N ;j++){
if(map[i][j] == 0 )vist[i][j] = false;
}
}
}
void map_init(){
for(int i = 0 ; i < N ; i++){
for(int j = 0; j < N ;j++){
vist[i][j] = false;
}
}
}
struct Node{
vector<pair<int,int> > v;
int rcnt = 0;
};
Node findGroup(int Y , int X , int curC ){
int rcnt = 0 ;
queue< pair<int,int> > q;
vector <pair<int,int> > v;
q.push({Y,X});
v.push_back({Y,X});
vist[Y][X] = true;
while (!q.empty()){
int curY = q.front().first;
int curX = q.front().second;
q.pop();
for(int k = 0 ; k < 4; k++){
int nY = curY + dir[k][0];
int nX = curX + dir[k][1];
if(nY < 0 || nY >= N || nX < 0 || nX >= N ) continue;
if( map[nY][nX] == -2 || map[nY][nX] == -1 || vist[nY][nX] ) continue;
if(map[nY][nX] == 0 || map[nY][nX] == curC){
vist[nY][nX] = true;
if(map[nY][nX] == 0 ) rcnt++;
v.push_back({ nY , nX });
q.push({nY,nX});
}
}
}
Node n;
n.v = v;
n.rcnt = rcnt;
return n;
}
void gravity(){
for (int i = N - 2; i >= 0; i--){
for (int j = 0; j < N; j++){
if (map[i][j] <= -1){
continue;
}
int y = i;
while (true){
if (y == N){
break;
}
int cur = map[y][j];
int next = map[y + 1][j];
if (next != -2){
break;
}
map[y + 1][j] = cur;
map[y][j] = -2;
y++;
}
}
}
}
void mat_turn(){
int tempBoard[22][22];
for (int i = 0; i < N; i++){
for (int j = 0; j < N; j++){
tempBoard[i][j] = map[i][j];
}
}
for (int i = 0; i < N; i++){
for (int j = 0; j < N; j++){
map[N - (j + 1)][i] = tempBoard[i][j];
}
}
}
void del(vector<pair<int,int> > &tv){
for(int idx = 0 ; idx < tv.size() ;idx++){
int cy = tv[idx].first;
int cx = tv[idx].second;
map[cy][cx] = -2;
}
}
int main(){
cin >> N >> M;
for(int i = 0 ; i < N ;i++){
for(int j =0; j < N ;j++){
cin >> map[i][j];
}
}
while (true){
map_init();
int cY = -10;
int cX = -10;
int csize = -10;
int crcnt = -10;
vector<pair<int,int> > dv;
for(int i = 0 ; i < N ;i ++){
for(int j = 0 ; j< N ;j++){
zero_init(); // 0 초기화
if( map[i][j] == 0|| map[i][j] == -2 || map[i][j] == -1 || vist[i][j] ) continue;
Node tv = findGroup(i,j,map[i][j]);
vist[i][j] = true;
int tmpsize = tv.v.size();
int tmprcnt = tv.rcnt ;
if(tmpsize >= 2 ){
if(csize < tmpsize ){
cY = tv.v[0].first;
cX = tv.v[0].second;
csize = tmpsize;
crcnt = tmprcnt;
dv = tv.v;
}else if(csize == tmpsize){
if(crcnt < tmprcnt ){
cY = tv.v[0].first;
cX = tv.v[0].second;
csize = tmpsize;
crcnt = tmprcnt;
dv = tv.v;
}else if(crcnt == tmprcnt){
if(cY < tv.v[0].first ){
cY = tv.v[0].first;
cX = tv.v[0].second;
csize = tmpsize;
crcnt = tmprcnt;
dv = tv.v;
}else if(cY == tv.v[0].first ){
if(cY == tv.v[0].first && cX < tv.v[0].second ){
cY = tv.v[0].first;
cX = tv.v[0].second;
csize = tmpsize;
crcnt = tmprcnt;
dv = tv.v;
}
}
}
}
}
}
}
if(csize == -10) break;
ans += (csize * csize);
del(dv);
gravity();
mat_turn();
gravity();
}
cout << ans ;
return 0;
}
'Algorithm > S사 코딩테스트' 카테고리의 다른 글
백준 마법사 상어와 복제 (0) | 2021.12.14 |
---|---|
백준 주사위 굴리기 2 (0) | 2021.12.14 |
백준 마법사상어와 비바라기 (0) | 2021.06.18 |
백준 마법사상어와 토네이도 (0) | 2021.06.18 |
백준 스타트택시 (0) | 2021.03.23 |
댓글