Notice
Recent Posts
Recent Comments
Link
«   2025/01   »
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
Archives
Today
Total
관리 메뉴

최's 먹공로그

BOJ3190_뱀 본문

APS

BOJ3190_뱀

ChoiSH313 2019. 6. 26. 21:08

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


문제요약

1. 사과를 먹으면 뱀 길이가 늘어난다

2. 벽 또는 자신의 몸에 부딪히면 게임이 끝난다

3. 게임이 시작할 때 뱀은 맨위 맨좌측(1,1)에 위치하고 뱀의 길이는 1 이다 , 처음에는 오른쪽으로 향한다

4. 매초 마다 이동하는 규칙

(1) 먼저 뱀은 몸길이를 늘려 머리를 다음칸에 위치시킨다

(2) 만약 이동한 칸에 사과가 있다면, 그 칸에 있던 사과가 없어지고 꼬리는 움직이지 않는다(몸 길이가 늘어난다)

(3) 만약 이동한 칸에 사과가 없다면, 몸길이를 줄여서 꼬리가 위치한 칸을 비워 준다

5. 사과의 위치와 뱀의 이동경로가 주어질 때 이 게임이 몇 초에 끝나는지 계산

6. 사과 : 사과의 위치는 모두 다르다 , (1,1)에는 사과가 없다

7. 뱀 이동 : X C , 게임 시작 시간으로부터 X초가 끝난 뒤에 C방향으로 90도 회전 , X는 10,000이하의 양의 정수 , C는 D오른쪽 L왼쪽


문제issue

1. 자신의 몸에 부딪히는 경우

-> map[r][c]가 1이면 break

2. 벽에 부딪히는 경우는 그냥 인덱스 넘어가면 종료

3. 처음에 뱀의 몸 길이가 늘어나는 부분과 뱀이 움직이는 부분이 헷갈려서

0 0 1 1 1 0            0 0 0 1 1 0 

0 0 0 0 2 0     ->    0 0 0 0 1 0

0 0 0 0 0 0            0 0 0 0 2 0

2가 뱀의 머리라고 했을 때 위와 같이 움직이면 꼬리부분을 0으로 만들고

머리와 몸통부분은 움직인다고 생각하고 어떤 몸통은 행을 증감시키고 어떤 몸통은 열을 증감시켜야 할지 헷갈렸음

계속 그리다 보니 그냥 머리만 추가 해주고 경우에 따라서 꼬리를 지울지 말지만 정해주면 됨

전 단계에서 머리였던 부분이 몸통으로 변함 즉, 몸통에 해당하는 배열의 인덱스를 따로 변화시킬 필요가 없었음

4. 뱀의 꼬리가 어디인지

-> 큐를 사용


해결흐름

1. 사과의 위치는 2 , 뱀은 1 , 빈칸 0 인 map을 만든다

2. 몇 초가 지났을 때 L 또는 D를 수행하기 위해서 char 배열을 만들어서

order_arr[몇초] = L 또는 D 이런식으로 세팅한다

3. 처음 뱀의 머리에 해당하는 부분을 큐에 add해준다

4. 방향 dir에 따라서 행 또는 열을 변화 시켜준다

5. 변화된 행 또는 열이 범위안인지 검사하고 범위밖이면 flag = ture 후 return한다

flag = true면 while문도 종료 시킨다

6. 범위안이면 빈 칸인지 0 , 사과인지 2 , 뱀의 일부인지 1로 나눈다

7. 빈 칸이면 q.poll해서 꼬리에 해당하는 칸을 꺼내주고 map에서 0으로 갱신해준뒤 , 새로운 머리 위치를 q.add해주고 map에도 갱신해준다

8. 사과면 visited 체크만 해준뒤 , map 갱신 , q.add만 해준다

9. 뱀의 몸이면 flag = true 해준뒤 return 해준다

10. order_arr[result]에 L 또는 D가 있으면 그때의 dir에 따라서 dir을 갱신해준다


소스코드

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
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
 
public class Main {
 
    static class pair {
        int r;
        int c;
 
        public pair(int r, int c) {
            super();
            this.r = r;
            this.c = c;
        }
    }
    
    private static int[] dr = {0,0,-1,1};
    private static int[] dc = {1,-1,0,0};
 
    private static int N;
    private static int dir;
    private static int s_r;
    private static int s_c;
    private static int result;
    private static boolean flag;
    private static LinkedList<pair> q;
    private static char[] order_arr;
    private static int[][] map;
    private static boolean[][] apple_visited;
 
    public static void main(String[] args) throws Exception {
 
        // input
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        N = Integer.parseInt(br.readLine().trim());
        map = new int[N + 1][N + 1];
        apple_visited = new boolean[N + 1][N + 1];
        int K = Integer.parseInt(br.readLine().trim());
        for (int i = 0; i < K; i++) {
            StringTokenizer st = new StringTokenizer(br.readLine().trim(), " ");
            // 사과위치
            map[Integer.parseInt(st.nextToken())][Integer.parseInt(st.nextToken())] = 2;
        }
        // 뱀의 처음 위치
        map[1][1= 1;
        int L = Integer.parseInt(br.readLine().trim());
        // 몇초가 지났을 때 회전하는 정보를 저장 , 몇초가 인덱스에 해당하고 거기에 L또는D를 저장
        order_arr = new char[10000];
        for (int i = 0; i < L; i++) {
            StringTokenizer st = new StringTokenizer(br.readLine().trim(), " ");
            order_arr[Integer.parseInt(st.nextToken())] = st.nextToken().charAt(0);
        }
 
        // start
        result = 0;
        dir = 0// 0오른쪽 , 1왼쪽 , 2위 , 3아래 처음에는 오른쪽
        s_r = 1// 뱀 처음 위치
        s_c = 1;
        q = new LinkedList<pair>();
        q.add(new pair(s_r, s_c));
        flag = false;
        while (true) {
            result++;
            // 방향에 따라서
            s_r += dr[dir];
            s_c += dc[dir];
            solve();
            if(flag)
                break;
        }
        System.out.println(result);
    } // end of main
 
    private static void solve() {
        // 범위 안이고
        if (s_c >= 1 && s_c <= N && s_r >= 1 && s_r <= N) {
            // 빈곳이면 머리 위치를 add해주고 , 꼬리는 poll해서 map을 갱신
            if (map[s_r][s_c] == 0) {
                pair p = q.poll();
                map[p.r][p.c] = 0;
                q.add(new pair(s_r, s_c));
                map[s_r][s_c] = 1;
            } else if (map[s_r][s_c] == 2 && !apple_visited[s_r][s_c]) {
                // 사과면
                apple_visited[s_r][s_c] = true;
                map[s_r][s_c] = 1;
                q.add(new pair(s_r, s_c));
            }
            // 뱀의 몸이면
            else if (map[s_r][s_c] == 1) {
                flag = true;
                return;
            }
        } else {
            // 범위를 넘어가면
            flag = true;
            return;
        }
        // 방향 검사하고 변경
        if (order_arr[result] == 'L') {
            if(dir==0)
                dir = 2;
            else if(dir == 1)
                dir = 3;
            else if(dir == 2)
                dir = 1;
            else if(dir == 3)
                dir = 0;
        } else if (order_arr[result] == 'D') {
            if(dir == 0)
                dir = 3;
            else if(dir == 1)
                dir = 2;
            else if(dir == 2)
                dir = 0;
            else if(dir == 3)
                dir = 1;
        }
    }
// end of class
cs

'APS' 카테고리의 다른 글

BOJ15683_감시  (4) 2019.06.29
BOJ14500_테트로미노  (2) 2019.06.26
BOJ14890_경사로  (4) 2019.06.19
BOJ17140_이차원배열과연산_못푼문제  (2) 2019.06.16
BOJ16234_인구 이동  (0) 2019.06.14