ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [BOJ]백준 21609번: 상어 중학교(C++)/Simulation
    Problem Solving/BOJ(백준) 2021. 6. 14. 03:11

    https://www.acmicpc.net/problem/21609

     

    21609번: 상어 중학교

    상어 중학교의 코딩 동아리에서 게임을 만들었다. 이 게임은 크기가 N×N인 격자에서 진행되고, 초기에 격자의 모든 칸에는 블록이 하나씩 들어있고, 블록은 검은색 블록, 무지개 블록, 일반 블록

    www.acmicpc.net

    내가 삼성 코테에서 접한 삼성 유형의 정수라고 할 수 있는 문제

    시뮬레이션+DFS+중력+배열회전이 전부 합쳐져서 처음 문제를 봤을 때 그냥 웃겼다

    요즘 삼성 유형은 주사위 윷놀이같은 끔찍한 문제가 더 안 나오는 걸 보니 이전보다 난이도를 낮추고 구현 능력에 포커스를 맞춘 것 같아 보인다

     

    상어 초등학교는 너무 쉬워서 당황했지만 상어 중학교는 요구사항이 엄청엄청엄청 많기 때문에 잘 정리하고 설계해야 한다

    나도 아래처럼 설계했음에도 그룹의 행열 우선순위와 기준블록의 행열 우선순위가 다른 것이 헷갈려서 잘못 구현했다

    보통 이런식으로 설계한 뒤 input 케이스들을 확인해보고, 틀렸다면 1️⃣함수 수도코드가 정확한지 2️⃣요구사항 정리->함수 설계로 갈 때 빼먹은 조건이 있는지 3️⃣문제의 조건들이 빠짐없이 정리 되었는지 등을 검사한다

     

    보통 123번 안에 실수한 것이 있다

    현재는 삼성 유형은 큰 어려움 없이 요구사항 정리 -> 설계 -> 구현 순으로 짤 수 있지만 아직 Not 삼성 유형은 그렇게까진 못하겠다

    방학 때 문제 많이많이 풀어야지

    #include <cstdio>
    #include <math.h>
    #include <cstring>
    #include <algorithm>
    #define pii pair<int,int>
    #define BLACK -1
    #define RAINBOW 0
    #define AIR -2
    using namespace std;
    
    typedef struct { int x, y; }point;
    int n, m, board[21][21],ans;
    int dx[] = { 1,0,-1,0 }, dy[] = { 0,1,0,-1 };
    bool visit[21][21];
    
    bool safe(int x, int y) {
    	return x >= 0 && x < n && y >= 0 && y < n;
    }
    
    pii dfs(point cur,int color) {
    	visit[cur.y][cur.x] = 1;
    	pii score = make_pair(0, 0);
    	if (board[cur.y][cur.x] == RAINBOW)score.second++;
    	else if (board[cur.y][cur.x] == color)score.first++;
    
    	for (int i = 0; i < 4; i++) {
    		int nx = cur.x + dx[i];
    		int ny = cur.y + dy[i];
    		if (safe(nx,ny)&&!visit[ny][nx] && (board[ny][nx] == color || board[ny][nx] == RAINBOW)) {
    			auto ret = dfs({ nx,ny }, color);
    			score.first += ret.first;
    			score.second += ret.second;
    		}
    	}
    	return score;
    }
    
    void popBlock(point cur, int color) {
    	board[cur.y][cur.x] = AIR;
    	visit[cur.y][cur.x] = 1;
    	
    	for (int i = 0; i < 4; i++) {
    		int nx = cur.x + dx[i];
    		int ny = cur.y + dy[i];
    		if (safe(nx, ny) && !visit[ny][nx] && (board[ny][nx] == color || board[ny][nx] == RAINBOW)) {
    			popBlock({ nx,ny }, color);
    		}
    	}
    }
    
    void gravity() {
    	for(int j=0;j<n;j++)
    		for (int i = n - 1; i >= 0; i--) {
    			if (board[i][j] < 0)continue;
    			int cur=i,next=i+1;
    			while (safe(j, next)&&board[next][j]==AIR) {
    				board[next][j] = board[cur][j];
    				board[cur][j] = AIR;
    				cur++;
    				next++;
    			}
    		}
    }
    
    void rotate() {
    	int temp[21][21];
    	for (int i = 0; i < n; i++)
    		for (int j = 0; j < n; j++)
    			temp[i][j] = board[j][n - 1 - i];
    	memcpy(board, temp, sizeof(temp));
    }
    
    bool game() {
    	pii score=make_pair(0,0);
    	point block = { -1,-1 };
    	memset(visit, false, sizeof(visit));
    	for(int i=0;i<n;i++)
    		for (int j = 0; j < n; j++) {
    			if (board[i][j] <= 0)continue;
    			point cur = { j,i };
    
    			auto x = dfs(cur, board[i][j]);
    			for (int a = 0; a < n; a++)for (int b = 0; b < n; b++)if (board[a][b] == RAINBOW)visit[a][b] = false;
    			
    			if (x.first + x.second < 2)continue;
    			if ((x.first + x.second > score.first + score.second)
    				||((x.first+x.second==score.first+score.second)&&(x.second>score.second))
    				|| ((x.first + x.second == score.first + score.second) && (x.second == score.second)&&(i>block.y))
    				|| ((x.first + x.second == score.first + score.second) && (x.second == score.second) && (i == block.y&&j>block.x))) {
    				score = x;
    				block = { j,i };
    			}
    		}
    	memset(visit, false, sizeof(visit));
    	if (block.x != -1) {
    		ans += pow(score.first + score.second, 2);
    		popBlock(block, board[block.y][block.x]);
    		gravity();
    		rotate();
    		gravity();
    		return true;
    	}
    	else return false;
    }
    
    int main() {
    	scanf("%d%d", &n, &m);
    	for (int i = 0; i < n; i++)
    		for (int j = 0; j < n; j++)
    			scanf("%d", &board[i][j]);
    	while (game());
    	printf("%d", ans);
    	return 0;
    }

     

    그리고 테스트케이스 예제 2번이 이해가 안 가서 디버깅할 때 힘들었는데 내가 구현한 동작과정 또한 첨부한당 ~_~

    더보기
    current score: 0
    ------------
    2 3 1 R B 2
    2 B 4 1 3 3
    3 R 4 2 2 1
    B 4 B 2 3 4
    3 B 4 2 R 3
    1 2 2 2 2 1
    ------------
    
    ------------
    2 3 1 R B 2
    2 B 4 1 3 3
    3 R 4     1
    B 4 B   3 4
    3 B 4     3
    1         1
    ------------
    
    ------------
    2
    B       3 1
      3 1 4 3 3
    1 4 4 B R 1
    3 B R 4 B 4
    2 2 3 B 3 1
    ------------
    
    current score: 81
    ------------
    2
    B       3 1
      3 1 4 3 3
    1 4 4 B R 1
    3 B R 4 B 4
    2 2 3 B 3 1
    ------------
    
    ------------
    2
    B       3 1
      3 1 4 3 3
    1     B R 1
    3 B     B 4
    2 2 3 B 3 1
    ------------
    
    ------------
          1 4 1
          R B 3
          B   B
      1 3   1 3
      3 3 3 B 2
    2 B 4 1 3 2
    ------------
    
    current score: 97
    ------------
          1 4 1
          R B 3
          B   B
      1 3   1 3
      3 3 3 B 2
    2 B 4 1 3 2
    ------------
    
    ------------
          1 4 1
          R B 3
          B   B
      1     1 3
            B 2
    2 B 4 1 3 2
    ------------
    
    ------------
      3 B   2 2
      B     B 3
        B     1
    1         4
    4     3   B
    1 R   1 1 2
    ------------
    
    current score: 113
    ------------
      3 B   2 2
      B     B 3
        B     1
    1         4
    4     3   B
    1 R   1 1 2
    ------------
    
    ------------
      3 B   2 2
      B     B 3
        B     1
    1         4
    4     3   B
          1 1 2
    ------------
    
    ------------
      3     B
    2 B
    2   1     2
    B   B     1
      B     3 1
    3     4 1 4
    ------------
    
    current score: 117
    ------------
      3     B
    2 B
    2   1     2
    B   B     1
      B     3 1
    3     4 1 4
    ------------
    
    ------------
      3     B
    2 B
    2   1     2
    B   B
      B     3
    3     4 1 4
    ------------
    
    ------------
    
    B
            2 4
          B 3 1
      B 1   B 4
    3 2 2 B   3
    ------------
    
    current score: 121
    ------------
    
    B
            2 4
          B 3 1
      B 1   B 4
    3 2 2 B   3
    ------------
    
    ------------
    
    B
            2 4
          B 3 1
      B 1   B 4
    3     B   3
    ------------
    
    ------------
          1 4
          3 B 3
          B   B
    
        4   B 1
      B 2     3
    ------------
    
    current score: 125
    ------------
          1 4
          3 B 3
          B   B
    
        4   B 1
      B 2     3
    ------------

     

Designed by Tistory.