ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [BOJ]백준 12100번: 2048(Easy) 풀이 및 반례
    Problem Solving/BOJ(백준) 2020. 4. 17. 22:19

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

     

    12100번: 2048 (Easy)

    첫째 줄에 보드의 크기 N (1 ≤ N ≤ 20)이 주어진다. 둘째 줄부터 N개의 줄에는 게임판의 초기 상태가 주어진다. 0은 빈 칸을 나타내며, 이외의 값은 모두 블록을 나타낸다. 블록에 쓰여 있는 수는 2보다 크거나 같고, 1024보다 작거나 같은 2의 제곱꼴이다. 블록은 적어도 하나 주어진다.

    www.acmicpc.net

    할만한가?싶다가도 ㅇㅏ닌 악마같은 문제.... 😠

    어찌보면 삼성 역량테스트의 표준같은 문제였당

     

    나는 두 가지 방법으로 문제를 풀었다

    ① 일단 역테 기출중에서 많이 쓰는, 모든 경우 완전탐색을 위해 DFS로 방향 경우의 수를 구한 뒤

    방향 순서에 따라 5번 이동을 해주고 배열 최댓값을 Result로 갱신

    이동 예시
    이동할 방향이 정해진 뒤 한꺼번에 이동

    하지만 이 풀이는,,,,, 상하좌우 모든 이동을 따로따로 구현해야 해서 코드가 엄청나게 더러워진다는 단점이 있었당 ㅠ

    그래서 이동 섹션을 한 번만 구현할 수 없을까.....? 하다가

    ② 배열 돌리기를 생각해냈다 .....

    90도 회전하고 위로 이동한 것 = 오른쪽으로 이동한 것

    그림을 보면

    원래 상태에서 배열을 90도 회전시킨 다음 위로 이동하면 오른쪽으로 이동한 것과 배열 상태가 같다

    는 것을 알 수 있다

    물론 배열이 회전되어있긴 하지만 문제에서는 상관없기 때문에 마구 돌려주자

    1번 방법에서처럼 방향을 전부 정한 뒤에 이동&회전을 해도 되지만

    다음 depth를 호출할 때 마다 이동&회전을 해줘도 된다

     

    1️⃣번풀이

    #include <cstdio>
    #include <stack>
    using namespace std;
    int n, ans, board[22][22], m[22][22], dx[] = { 1,0,-1,0 }, dy[] = { 0,1,0,-1 }, seq[8];
    stack<int> s[22];
    void move(int arr[][22], int dir) {
    	switch (dir) {
    	case 0:	//동
    		for (int i = 0; i < n; i++)
    			for (int j = n - 1, check = 0; j >= 0; j--) {
    				if (!arr[i][j])continue;
    				if (!s[i].empty() && !check && s[i].top() == arr[i][j]) {
    					s[i].pop();
    					s[i].push(arr[i][j] * 2);
    					check = 1;
    				}
    				else {
    					s[i].push(arr[i][j]);
    					check = 0;
    				}
    				arr[i][j] = 0;
    			}
    		for (int i = 0; i < n; i++)
    			while (!s[i].empty()) {
    				arr[i][n - s[i].size()] = s[i].top();
    				s[i].pop();
    			}
    		break;
    	case 1:	//남
    		for (int i = 0; i < n; i++)
    			for (int j = n - 1, check = 0; j >= 0; j--) {
    				if (!arr[j][i])continue;
    				if (!s[i].empty() && !check && s[i].top() == arr[j][i]) {
    					s[i].pop();
    					s[i].push(arr[j][i] * 2);
    					check = 1;
    				}
    				else {
    					s[i].push(arr[j][i]);
    					check = 0;
    				}
    
    				arr[j][i] = 0;
    			}
    		for (int i = 0; i < n; i++)
    			while (!s[i].empty()) {
    				arr[n - s[i].size()][i] = s[i].top();
    				s[i].pop();
    			}
    		break;
    	case 2:	//서
    		for (int i = 0; i < n; i++)
    			for (int j = 0, check = 0; j < n; j++) {
    				if (!arr[i][j])continue;
    				if (!s[i].empty() && !check && s[i].top() == arr[i][j]) {
    					s[i].pop();
    					s[i].push(arr[i][j] * 2);
    					check = 1;
    				}
    				else {
    					s[i].push(arr[i][j]);
    					check = 0;
    				}
    
    				arr[i][j] = 0;
    			}
    		for (int i = 0; i < n; i++)
    			while (!s[i].empty()) {
    				arr[i][s[i].size() - 1] = s[i].top();
    				s[i].pop();
    			}
    		break;
    	case 3:	//북
    		for (int i = 0; i < n; i++)
    			for (int j = 0, check = 0; j < n; j++) {
    				if (!arr[j][i])continue;
    				if (!s[i].empty() && !check && s[i].top() == arr[j][i]) {
    					s[i].pop();
    					s[i].push(arr[j][i] * 2);
    					check = 1;
    				}
    				else {
    					s[i].push(arr[j][i]);
    					check = 0;
    				}
    
    				arr[j][i] = 0;
    			}
    		for (int i = 0; i < n; i++)
    			while (!s[i].empty()) {
    				arr[s[i].size() - 1][i] = s[i].top();
    				s[i].pop();
    			}
    		break;
    	}
    }
    void func(int dep) {
    	if (dep == 5) {
    		for (int i = 0; i < n; i++)for (int j = 0; j < n; j++)
    			m[i][j] = board[i][j];
    		//복사
    
    		for (int i = 0; i < 5; i++)
    			move(m, seq[i]);
    
    		for (int i = 0; i < n; i++)for (int j = 0; j < n; j++)
    			if (m[i][j] > ans)ans = m[i][j];
    		return;
    	}
    
    	for (int i = 0; i < 4; i++) {
    		seq[dep] = i;
    		func(dep + 1);
    	}
    }
    int main() {
    	scanf("%d", &n);
    	for (int i = 0; i < n; i++)
    		for (int j = 0; j < n; j++)
    			scanf("%d", &board[i][j]);
    	func(0);
    	printf("%d", ans);
    	return 0;
    }

    2️⃣번풀이

    #include <cstdio>
    #include <cstring>
    #include <stack>
    using namespace std;
    int n, ans, board[22][22], m[22][22], dx[] = { 1,0,-1,0 }, dy[] = { 0,1,0,-1 };
    int seq[5], kk[] = { 0,3,0,1,3 };
    stack<int> s[22];
    void move(int arr[][22]) {
    	for (int i = 0; i < n; i++)
    		for (int j = 0, check = 0; j < n; j++) {
    			if (!arr[j][i])continue;
    			if (!s[i].empty() && !check && s[i].top() == arr[j][i]) {
    				s[i].pop();
    				s[i].push(arr[j][i] * 2);
    				check = 1;
    			}
    			else {
    				s[i].push(arr[j][i]);
    				check = 0;
    			}
    
    			arr[j][i] = 0;
    		}
    	for (int i = 0; i < n; i++)
    		while (!s[i].empty()) {
    			arr[s[i].size() - 1][i] = s[i].top();
    			s[i].pop();
    		}
    }
    void rotate(int arr[][22]) {
    	for (int i = 0; i < n; i++)
    		for (int j = 0; j < n; j++)
    			m[j][n - 1 - i] = arr[i][j];
    	memcpy(arr, m, sizeof(m));
    }
    void func(int dep) {
    	if (dep == 5) {
    		for (int i = 0; i < n; i++)
    			for (int j = 0; j < n; j++)
    				if (board[i][j] > ans)ans = board[i][j];
    		return;
    	}
    
    	int temp[22][22];
    	for (int i = 0; i < 4; i++) {
    		memcpy(temp, board, sizeof(board));
    		move(board);
    		seq[dep] = i;
    		func(dep + 1);
    		memcpy(board, temp, sizeof(board));
    		rotate(board);
    	}
    }
    int main() {
    	scanf("%d", &n);
    	for (int i = 0; i < n; i++)
    		for (int j = 0; j < n; j++)
    			scanf("%d", &board[i][j]);
    	func(0);
    	printf("%d", ans);
    	return 0;
    }

    2번 풀이 코드가 1번 풀이 코드의 절반 길이다 ^^

    각 경우의 수는 4^5 = 1024번이고 각각의 경우에 대해 4번씩 회전(시간복잡도 O(n^2)) * 이동(시간복잡도 O(n^2))

    굉장히 복잡하당 ...

     

    반례👇👇👇

    더보기

    #1

    3

    2 2 2

    4 4 4

    8 8 8 

    =>16

     

    #2

    2

    8 16

    16 8

    =>16

     

    #3

    4

    8 16 0 0

    0 0 16 8

    0 0 0 0

    0 0 0 0

    =>32

     

    4
    0 0 0 0
    4 0 0 0
    8 32 4 0
    8 8 4 0
    ->64

     

    10
    8 8 4 16 32 0 0 8 8 8
    8 8 4 0 0 8 0 0 0 0
    16 0 0 16 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 16
    0 0 0 0 0 0 0 0 0 2
    ->128

     

    10
    16 16 8 32 32 0 0 8 8 8
    16 0 0 0 0 8 0 0 0 16
    0 0 0 0 0 0 0 0 0 2
    0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0
    ->64

     

    10
    0 0 0 0 0 32 8 64 8 16
    0 0 0 0 0 0 0 16 8 16
    0 0 0 0 0 0 0 0 0 2
    0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0
    ->128

     

Designed by Tistory.