반응형

문제 링크: https://www.acmicpc.net/problem/12094

 

12094번: 2048 (Hard)

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

www.acmicpc.net

<문제 풀이> 백트랙킹

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

 

12100번: 2048 (Easy)

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

www.acmicpc.net

2048 Easy 문제에서 백트랙킹이 추가된 문제이다.

 

1. 이동 후 항상 변화가 있어야 한다. (이동 후 배열의 값이 바뀌었는지 체크)

2 4 8

2 4 8 

2 4 8

에서 left를 하면

2 4 8

2 4 8

2 4 8

변화가 없는 상태에서 계속 연산을 해봤자 의미가 없다. 

-> 최대 k 번까지 이동했을 때 최댓값을 구하고 싶은 거니깐 항상 변화가 있어야 한다.

 

2. k번 이동했을 때 현재 배열의 값으로 10번까지 이동해서 만들 수 있는 최댓값이 지금 까지 갱신한 최댓값 이하이면  더 이상 진행하지 않는다.

1번 이동했을 때 현재 배열의 값의 최대값이 2라면

10번 이동했을 때 현재 배열의 최댓값으로 만들 수 있는 수는 2048이다.

2 * 2 ^ (10 - 1) = 1024  -> ( 현재 배열의 값의 최대값 * 2^(10 - k) ) 

그런데 지금까지 갱신한 최댓값이 4096이라면

아무리 최고의 상황이 나오더라도 10번까지 이동해서 4096을 만들 수 없다

 

 

<C++ 소스 코드>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
#include <iostream>
#include <string>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <utility>
#include <climits>
#include <cmath>
#include <deque>
#include <cstdlib>
using namespace std;
 
int N;
int board[20][20];
bool visited[20][20];
int res = 0;
int max_res = 0;
void printBoard() {
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            cout << board[i][j] << ' ';
        }
        cout << '\n';
    }
    cout << "\n\n";
}
 
void rotate() {
    int temp[20][20];
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            temp[i][j] = board[i][j];
        }
    }
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            board[i][j] = temp[N - j - 1][i];
        }
    }
}
 
 
void left() {
    for (int i = 0; i < N; i++) {
        int moved[20= { 0, };
        bool combined[20= { 0, };
        int idx = 0;
        for (int j = 0; j < N; j++) {
            if (board[i][j] == 0continue;
            if (moved[idx] == 0) {
                moved[idx] = board[i][j];
            }
            else if (moved[idx] && combined[idx]) {
                moved[++idx] = board[i][j];
            }
            else if (moved[idx] == board[i][j]){
                moved[idx] *= 2;
                combined[idx++= true;
           
            }
            else {
                moved[++idx] = board[i][j];
            }
 
            
        }
        for (int j = 0; j < N; j++) {
            board[i][j] = moved[j];
        }
    }
}
 
void up() {
    rotate();
    rotate();
    rotate();
    left();
    rotate();
}
void right() {
    rotate();
    rotate();
    left();
    rotate();
    rotate();
 
}
 
void down() {
    rotate();
    left();
    rotate();
    rotate();
    rotate();
}
 
void tempToBoard(int temp[][20]) {
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            board[i][j] = temp[i][j];
        }
    }
}
 
bool isChanged(int arr1[][20], int arr2[][20]) {
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            if (arr1[i][j] != arr2[i][j]) return true;
        }
    }
    return false;
}
 
void dfs(int k) {
    int temp[20][20];
    int cur_max = 0;
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            temp[i][j] = board[i][j];
            if (board[i][j] >= cur_max) cur_max = board[i][j];
        }
    }
    res = max(res, cur_max);
 
    if (k == 10return;
    if (cur_max * 1 << (10 - k) <= res) return;
 
    left();
    if (isChanged(temp, board)) {
        dfs(k + 1);
        tempToBoard(temp);
    }
    right();
    if (isChanged(temp, board)) {
        dfs(k + 1);
        tempToBoard(temp);
    }
    up();
    if (isChanged(temp, board)) {
        dfs(k + 1);
        tempToBoard(temp);
    }
    down();
    if (isChanged(temp, board)) {
        dfs(k + 1);
        tempToBoard(temp);
    }
 
 
 
 
}
 
int main(void) {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    cin >> N;
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            cin >> board[i][j];
            if (board[i][j] >= max_res) max_res = board[i][j];
        }
    }
    
    dfs(0);
    cout << res;
   
    return 0;
}
 
 
cs

 

반응형

'알고리즘 문제풀이 > 백준' 카테고리의 다른 글

[백준 11559번] Puyo Puyo  (0) 2022.01.13
[백준 15686번] 치킨 배달  (0) 2022.01.09
[백준 12100번] 2048(Easy)  (0) 2022.01.05
[백준 18808번] 스티커 붙이기  (0) 2022.01.05
[백준 2636번] 치즈  (0) 2022.01.05

+ Recent posts