문제 링크: https://www.acmicpc.net/problem/12094
<문제 풀이> 백트랙킹
https://www.acmicpc.net/problem/12100
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] == 0) continue;
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 == 10) return;
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 |