알고리즘/BaekJoon

백준 3190 : 뱀

꾸준하게 :) 2020. 2. 20. 20:38

문제 링크입니다 https://www.acmicpc.net/problem/3190

 

3190번: 뱀

문제  'Dummy' 라는 도스게임이 있다. 이 게임에는 뱀이 나와서 기어다니는데, 사과를 먹으면 뱀 길이가 늘어난다. 뱀이 이리저리 기어다니다가 벽 또는 자기자신의 몸과 부딪히면 게임이 끝난다. 게임은 NxN 정사각 보드위에서 진행되고, 몇몇 칸에는 사과가 놓여져 있다. 보드의 상하좌우 끝에 벽이 있다. 게임이 시작할때 뱀은 맨위 맨좌측에 위치하고 뱀의 길이는 1 이다. 뱀은 처음에 오른쪽을 향한다. 뱀은 매 초마다 이동을 하는데 다음과 같은 규칙을 따

www.acmicpc.net

문제에서 주어진 순서대로 차근차근 구현하였고, map에서 뱀을 8, 사과를 1로 놓고 풀었습니다.

풀이 방법을 순서대로 나열하면 다음과 같습니다. 

 

1. 뱀의 다음 위치를 Queue에 push 합니다.

   (시작 좌표의 오른쪽 칸)

 

2. Queue에서 pop을 한 후, 게임 경과 시간을 늘리고, 현재 칸을 꼬리 정보 벡터에 push 합니다.

3. 현재 칸에 사과가 없다면 꼬리칸을 0으로 만들고 현재 칸을 8로 만듭니다.

   (사과가 있다면 그냥 현재 칸을 8로 만들면 됩니다)

 

4. 입력으로 주어진 방향 전환 정보를 확인하고, 다음 칸의 방향을 결정한 후 다음 칸의 좌표를 결정합니다.

5. 뱀의 다음 칸의 값이 8이거나, 다음 칸이 벽이라면 경과된 시간을 출력하고, 아니라면 다음 위치를 Queue에 push 합니다.

 

 

[소스코드]

 

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
// [백준] 삼성 SW 역량 테스트 기출 문제 : 뱀(3190)
 
#include<vector>
#include<cstdio>
#include<queue>
using namespace std;
const int MAX = 100 + 10;
 
// 좌표와 방향을 저장하기 위한 구조체
struct p {
    int y, x, d;
};
vector <p> myTail;    // 꼬리의 위치를 저장하기 위한 벡터
 
// 방향 전환 정보 : rotation[sec] = dir 이면 sec초 후에 dir로 전환하십시오
int n, k, a, b, L, s, rotation[MAX * MAX], map[MAX][MAX];
 
const int dy[] = { -1010 };
const int dx[] = { 0-101 };
 
// 좌표와 방향을 인자로 받아서 p type으로 바꿔주는 함수
p make_p(int y, int x, int d) {
    p temp;
    
    temp.y = y, temp.x = x, temp.d = d;
    return temp;
}
 
void bfs(int y, int x) {
    
    int game_time = 0, tail = 0;         // 게임 시간, 꼬리 벡터 인덱스
    queue <p> q;
 
    map[y][x] = 8;                        // 시작 좌표에 뱀이 있다고 표시
    q.push(make_p(y, x + 13));         // 바로 오른쪽 좌표를 큐에 넣고
    myTail.push_back(make_p(y, x, 0));    // 시작 좌표도 꼬리 벡터에 넣습니다
    
    while (!q.empty()) {
 
        p cur = q.front();
        q.pop();
        game_time++;
 
        // 지금 현재 뱀의 위치를 꼬리 벡터에 계속 push 해줍니다
        myTail.push_back(make_p(cur.y, cur.x, 0));
 
        // 현재 칸에 사과가 없다면 꼬리가 있는 칸을 0으로 만들고
        // 꼬리 벡터 인덱스를 증가시킵니다
        if (map[cur.y][cur.x] == 0)
            map[myTail[tail].y][myTail[tail++].x] = 0;
 
        map[cur.y][cur.x] = 8;    // 현재 칸에 뱀을 넣어줍니다
 
        int yy, xx, dd;
 
        // roatation 배열에 방향 전환 정보를 보고 알맞게 방향을 설정합니다
        if (rotation[game_time] == -1) {
            dd = (cur.d + 3) % 4;
        }
        else if (rotation[game_time] == 1) {
            dd = (cur.d + 1) % 4;
        }
        else dd = cur.d;    // 방향 전환 시간이 아니면 그냥 현재 방향
 
        yy = cur.y + dy[dd], xx = cur.x + dx[dd];    // 다음 칸의 좌표 설정
 
        if (map[yy][xx] == 8 || yy <= 0 || yy > n || xx <= 0 || xx > n) {
            break;    // 다음 칸이 벽이거나 다음 칸에 뱀이 있으면
        }
        q.push(make_p(yy, xx, dd));    // 다음 칸을 Queue에 push
    }
    printf("%d", game_time + 1);
}
 
void solve(void) {
 
    scanf("%d%d"&n, &k);
    for (int i = 0; i < k; i++) {
        scanf("%d%d"&a, &b);
        map[a][b] = 1;
    }
    scanf("%d"&L);
    for (int i = 0; i < L; i++) {
        char w;
        scanf("%d %c"&s, &w);
 
        if (w == 'L') rotation[s] = 1;    // s초 후에 왼쪽(1)으로 90도 전환해라
        else rotation[s] = -1;            // s초 후에 오른쪽(-1)으로 90도 전환해라
    }
    bfs(11);    // (1, 1)부터 시작
}
 
int main(void) {
    solve();
    return 0;
}
cs

 

'알고리즘 > BaekJoon' 카테고리의 다른 글

백준 10448 : 유레카 이론  (0) 2020.02.21
백준 13460 : 구슬 탈출 2  (0) 2020.02.21
백준 14888 : 연산자 끼워넣기  (0) 2020.02.20
백준 14501 : 퇴사  (0) 2020.02.20
백준 11403 : 경로 찾기  (0) 2020.02.19