본문 바로가기

Study/BOJ

BOJ - 청소년 상어(19236)

이 문제는 상어가 갈 수 있는 칸 중 어떤 칸을 가느냐에 따라 최댓값이 달라지기 때문에 backtracking을 사용해야 하기 때문에 재귀적인 방법으로 풀어야만 한다.

 

문제의 아이디어는 바로 떠올랐는데 이를 어떻게 코드화 할지가 쉽게 떠오르지 않아서 시간이 좀 걸렸던 것 같다.


코드

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
#include<iostream>
#include<vector>
using namespace std;
int dx[9= {0-1-101110-1};
int dy[9= {00-1-1-10111};
int map[5][5];
typedef struct fish
{
    int x;
    int y;
    int dir;
}fish;
fish shark;
fish f[17];
int res;
 
void dfs(fish f[17], int map[5][5], fish shark, int score)
{
    res = max(res, score);
    for (int i=1; i<= 16; i++)
    {
        int x = f[i].x;
        int y = f[i].y;
        int dir = f[i].dir;
 
        if (dir == -1)
            continue;
 
        int flag = 0;
        int nx, ny;
        int j;
        for(j=0; j<8; j++)
        {
            nx = x + dx[dir];
            ny = y + dy[dir];
            if (nx <=0 || ny <=0 || nx > 4 || ny > 4)
            {
                f[i].dir = (dir == 8) ? 1 : dir + 1;
                dir = f[i].dir;
                continue;
            }
 
            if (nx == shark.x && ny == shark.y)
            {
                f[i].dir = (dir == 8) ? 1 : dir + 1;
                dir = f[i].dir;
                continue;
            }
            break;
        }
        if (j == 8)
            continue;
 
        int nidx = map[nx][ny];
 
        if (nidx > 0)
        {
            f[nidx].x = x;
            f[nidx].y = y;
            map[x][y] = nidx;
        }
        else
            map[x][y] = 0;
 
        f[i].x = nx;
        f[i].y = ny;
        map[nx][ny] = i;
    } //물고기 이동
    int sx = shark.x;
    int sy = shark.y;
    int sd = shark.dir;
 
    for(int i=1; i<=3; i++)
    {
        fish tmp[17];
 
        for(int j=1; j<=16; j++)
            tmp[j] = f[j];
 
        int tmp_map[5][5];
 
        for(int j=1; j<=4; j++)
            for(int k=1; k<=4; k++)
                tmp_map[j][k] = map[j][k];
 
        int nx = sx + dx[sd] * i;
        int ny = sy + dy[sd] * i;
        //map[nx][ny] == 0 물고기가 없는 경우
        if (nx <= 0 || ny <= 0 || nx > 4 || ny > 4 || map[nx][ny] == 0)
            continue;
 
        shark.x = nx;
        shark.y = ny;
        int num = tmp_map[nx][ny];
        tmp_map[nx][ny] = 0;
        shark.dir = tmp[num].dir;
        tmp[num].dir = -1;
 
        dfs(tmp, tmp_map, shark, score + num);
    }
}
 
 
int main()
{
    cin.tie(NULL);
    ios_base::sync_with_stdio(false);
    for(int i=1; i<=4; i++)
    {
        for(int j=1; j<=4; j++)
        {
            int num;
            fish tmp;
            cin >> num >> tmp.dir;
            tmp.x = i; tmp.y = j;
            f[num] = tmp;
            map[i][j] = num;
        }
    }
    res = map[1][1];
    shark.dir = f[res].dir;
    f[res].dir = -1;
    shark.x = 1; shark.y = 1;
    map[1][1= 0//상어
    dfs (f, map, shark, res);
    cout << res << "\n";
    return (0);
}
cs

해당 물고기가 잡혔다는 것을 표시하기 위해 dir에 -1을 넣었고, map상에서 해당 위치에 상어가 있거나 물고기가 없을 경우에 0을 대입하도록 하였다. 


재귀로 호출할 다음 변수를 만들어주는 부분이 핵심이었다.

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
    int sx = shark.x;
    int sy = shark.y;
    int sd = shark.dir;
 
    for(int i=1; i<=3; i++)
    {
        fish tmp[17];
 
        for(int j=1; j<=16; j++)
            tmp[j] = f[j];
 
        int tmp_map[5][5];
 
        for(int j=1; j<=4; j++)
            for(int k=1; k<=4; k++)
                tmp_map[j][k] = map[j][k];
 
        int nx = sx + dx[sd] * i;
        int ny = sy + dy[sd] * i;
        //map[nx][ny] == 0 물고기가 없는 경우
        if (nx <= 0 || ny <= 0 || nx > 4 || ny > 4 || map[nx][ny] == 0)
            continue;
 
        shark.x = nx;
        shark.y = ny;
        int num = tmp_map[nx][ny];
        tmp_map[nx][ny] = 0;
        shark.dir = tmp[num].dir;
        tmp[num].dir = -1;
 
        dfs(tmp, tmp_map, shark, score + num);
    }
cs

 

물고기의 위치를 저장하고 있는 f의 임시 배열 tmp, 물고기의 번호를 저장하고 있는 map의 임시 배열 tmp_map을 만들어

dfs() 함수의 parameter로 넘겨주게 되면, 항상 tmp와 tmp_map에는 호출된 parameter에 의해 결정되기 때문에

 

상어가 1칸, 2칸, 3칸을 간 각각의 경우의 map이 기존의 map에 영향을 주지 않은채로 (tmp_map에 저장하여 넘기기 때문에)

 

상어가 잡을 수 있는 물고기 번호의 최댓값을 계산할 수 있게 되는 것이다.

 

이러한 방법을 잘 알아놓고 다음에 문제풀 땐 바로 떠올릴 수 있도록 연습해야겠다.

'Study > BOJ' 카테고리의 다른 글

BOJ - 네트워크 연결(1922)  (0) 2021.04.15
BOJ - 거짓말(1043)  (0) 2021.04.14
BOJ - 최소 스패닝 트리(1197)  (0) 2021.04.14
BOJ - 미네랄(2933)  (0) 2021.04.12
BOJ - 마법사 상어와 파이어스톰(20058)  (0) 2021.04.10