반응형
문제 링크: https://www.acmicpc.net/problem/19236
19236번: 청소년 상어
첫째 줄부터 4개의 줄에 각 칸의 들어있는 물고기의 정보가 1번 행부터 순서대로 주어진다. 물고기의 정보는 두 정수 ai, bi로 이루어져 있고, ai는 물고기의 번호, bi는 방향을 의미한다. 방향 bi는
www.acmicpc.net
<문제 풀이> 백 트랙킹
이 문제는 백트래킹을 할 때 상태 정보 백업 및 복원이 가장 핵심입니다.
상어를 1칸 이동, 2칸 이동, 3칸 이동시키고 각각에 대해서 재귀 호출할 때 재귀 호출 전에 백업, 호출 후 복원을 하면 되고, 물고기들이 이동하는 건 클래스로 좌표와 방향을 저장해 두고 1번부터 16번까지 단순히 움직이면 됩니다.
이때 주의할 점은 상어는 물고기가 있는 칸만 이동할 수 있습니다.
(2칸에 물고기가 없다고 끝내면 안 되고 3칸도 이동해 보아야 한다.)
<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
|
#include<iostream>
#include<algorithm>
using namespace std;
#define SHARK -1
#define EMPTY -2
class pos {
public:
int x, y, dir;
void rotate() {
dir++;
if (dir == 9) dir = 1;
}
void del() {
x = -1; y = -1; dir = -1;
}
bool exist() {
if (x == -1 && y == -1 && dir == -1) return false;
else return true;
}
};
const int dx[9] = {0, -1, -1, 0, 1, 1, 1, 0, -1};
const int dy[9] = {0, 0, -1, -1, -1, 0, 1, 1, 1};
pos info[17]; //1~16번 좌표 방향 정보
int board[4][4];
pos shark; //현재 상어 상태
int res = 0;
void move() {
for (int i = 1; i <= 16; i++) {
if (!info[i].exist()) continue;
int startDir = info[i].dir;
while (true) {
int nx = info[i].x + dx[info[i].dir];
int ny = info[i].y + dy[info[i].dir];
int next = board[nx][ny];
if (nx < 0 || ny < 0 || nx >= 4 || ny >= 4 || board[nx][ny] == SHARK) {
info[i].rotate();
if (startDir == info[i].dir)break;
continue;
}
if (board[nx][ny] == EMPTY) {
board[nx][ny] = i;
board[info[i].x][info[i].y] = EMPTY;
info[i].x = nx;
info[i].y = ny;
}
else {
swap(board[info[i].x][info[i].y], board[nx][ny]);
swap(info[i], info[next]);
swap(info[i].dir, info[next].dir);
}
break;
}
}
}
/*백트랙킹 상태 정보 백업용*/
void backupBoard(int des[4][4], int src[4][4]) {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
des[i][j] = src[i][j];
}
}
}
void backupInfo(pos des[17], pos src[17]) {
for (int i = 0; i < 17; i++) {
des[i] = src[i];
}
}
void solve(int sum) {
move();
int cx = shark.x;
int cy = shark.y;
int dir = shark.dir;
for (int k = 1; k <= 3; k++) {
int nx = cx + dx[dir] * k;
int ny = cy + dy[dir] * k;
if (nx < 0 || ny < 0 || nx >= 4 || ny >= 4) return;
if (board[nx][ny] == EMPTY) continue;
int tempBoard[4][4];
pos tempInfo[17];
backupBoard(tempBoard, board);
backupInfo(tempInfo, info);
shark.x = nx;
shark.y = ny;
int num = board[nx][ny];
res = max(res, sum + num);
shark.dir = info[num].dir;
board[nx][ny] = SHARK;
board[cx][cy] = EMPTY;
info[num].del();
solve(sum + num);
shark.x = cx;
shark.y = cy;
shark.dir = dir;
backupBoard(board, tempBoard);
backupInfo(info, tempInfo);
}
}
int main(void) {
ios_base::sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
int a, b;
cin >> a >> b;
info[a].dir = b;
info[a].x = i;
info[a].y = j;
board[i][j] = a;
}
}
shark.x = 0;
shark.y = 0;
shark.dir = info[board[0][0]].dir;
info[board[0][0]].del();
int num = board[0][0];
board[0][0] = SHARK;
solve(num);
cout << res;
return 0;
}
|
cs |
반응형
'알고리즘 문제풀이 > 백준' 카테고리의 다른 글
[백준 1932번] 정수 삼각형 (0) | 2022.05.06 |
---|---|
[백준 19237번] 어른 상어 (0) | 2022.04.04 |
[백준 16236번] 아기 상어 (0) | 2022.03.30 |
[백준 17142번] 연구소 3 (0) | 2022.03.30 |
[백준 20055번] 컨베이어 벨트 위의 로봇 (0) | 2022.03.26 |