티스토리 뷰

반응형


#. Problem

* The copyright in this matter is in BOJ

 



#. Resolution Process

  1. Read and understand problem

  2. Redefine the problem + abstract

  3. Create solution plan (select Algorithm, Data structure)

  4. Prove the plan (check performance time and usage memory)

  5. Carry out the plan

  6. Look back on the plan and find a way to improve it



#. Solve


제시된 1초 동안 일어나는 일을 구현하는 문제다.

1. 낚시왕이 오른쪽으로 한 칸 이동 (가장 오른쪽 칸으로 이동하면 종료)

2. 낚시왕이 있는 열에 있는 상어 중에서 땅과 제일 가까운 상어를 잡음. 상어를 잡으면 격자판에서 잡은 상어가 사라짐

3. 상어가 이동 

       => 상어가 이동을 마친 후 한 칸에 상어가 두 마리 이상 있을 경우 크기가 가장 큰 상어가 나머지 상어를 모두 잡아먹음


여기서 신경을 써주어야 할 "Point" !!

1. 상어가 이동을 마쳤을 때, 방향을 반대로 바뀐 상태로 있다면 바뀐 방향 정보를 상어가 가지고 있어야 한다.

방향 전환을 편하게 구현하기 위해 상(0), 좌(1), 우(2), 하(3) 순서대로 방향을 설정했는데

이렇게 설정한 이유는, 

상 -> 하, 로 방향을 바꿀 경우 3 - 0(상) = 3(하)

하 -> 상, 로 방향을 바꿀 경우 3 - 3(하) = 0(상)

좌 -> 우, 로 방향을 바꿀 경우 3 - 1(좌) = 2(우)

우 -> 좌, 로 방향을 바꿀 경우 3 - 2(우) = 1(좌)


2. 상어의 정보를 담은 map은 계속 초기화가 되어야 한다.

이전에 사용했던 map 정보를 계속 사용할 경우 아래와 같은 예외 상황이 발생

아직 이동하지 않은 A 상어가 (3, 3)에 있는데, 

B 상어가 (3, 3)으로 이동할 경우 A 상어가 이미 이동해있다고 착각을 해버려서 두 상어는 싸우게 된다.

A 상어는 아직 이동하지도 않았는데..


#. Code


상어의 이동을 매초 한 칸씩 이동해서 실행 시간이 오래 걸린 것 같다.


최대 상어 수 10000

최대 속력 1000

최대 열 100


중간중간 잡히거나 잡아먹힌 상어가 있어서 시간복잡도 계산은 어렵긴 하지만

열 마다 모든 상어가 최대 속력으로 이동하는데 한 칸씩 이동하면 시간이 꾀나 걸릴것 같긴 하다..

이동을 연산으로 한 번에 처리 개선이 필요하다 !


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
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
 
public class BOJ17143 {
 
    static int R, C, M, map[][], king;
    static Shark[] sharks;
    static int[] dr = {-1001}, dc = {0-110}; // 상, 좌, 우, 하
    
    public static void main(String[] args) throws IOException {
 
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        
        R = Integer.parseInt(st.nextToken()); // 세로
        C = Integer.parseInt(st.nextToken()); // 가로
        M = Integer.parseInt(st.nextToken()); // 상어의 수
        map = new int[R + 1][C + 1];
        sharks = new Shark[M + 1];
        
        for (int i = 1; i <= M; i++) {
            st = new StringTokenizer(br.readLine());
            int r = Integer.parseInt(st.nextToken()); 
            int c = Integer.parseInt(st.nextToken()); 
            int s = Integer.parseInt(st.nextToken()); // 속력
            int d = Integer.parseInt(st.nextToken()); // 이동방향
            int z = Integer.parseInt(st.nextToken()); // 크기
            // 초기 방향 설정
            if(d == 1) d = 0;
            else if(d == 2) d = 3;
            else if(d == 3) d = 2;
            else d = 1;
            
            map[r][c] = i;
            sharks[i] = new Shark(r, c, s, d, z);
        }
        
        System.out.println(process());
    }
 
    private static int process() {
        
        int res = 0;
        
        // 1. 낚시왕이 오른쪽으로 한 칸 이동
        while(king++ < C) {
            // 2. 낚시왕이 상어를 잡는다.
            res += fishing();
            
            // 3. 상어가 이동
            move();
        }
        
        return res;
    }
 
    private static void move() {
        
        map = new int[R + 1][C + 1];
        
        for (int i = 1; i <= M; i++) {
            // 이미 잡힌 상어는 pass
            if(sharks[i] == nullcontinue;
            
            Shark now = sharks[i];
            int turn = 1, r = now.r, c = now.c;
            for (int m = 0; m < now.s; m++) {
                r += turn * dr[now.d]; 
                c += turn * dc[now.d];
                // 범위를 벗어날 경우
                if(r < 1 || r > R || c < 1 || c > C) {
                    // 방향을 반대로 하고
                    turn *= -1;
                    // 이전 칸으로 이동
                    r += (turn * dr[now.d]) * 2
                    c += (turn * dc[now.d]) * 2;
                }
            }
            
            // 상어의 방향이 바뀐 상태라면
            if(turn == -1) {
                sharks[i].d = 3 - sharks[i].d; 
            }
            
            // 이동한 칸에 다른 상어가 있을 경우
            if(map[r][c] > 0) {
                // 현재 상어보다 더 큰 상어일 경우 잡아먹힌다..
                if(sharks[map[r][c]].z > now.z) sharks[i] = null;
                // 현재 상어가 더 클 경우
                else {
                    sharks[i].r = r;
                    sharks[i].c = c;
                    // 해당 칸에 있던 상어를 잡아먹자.
                    sharks[map[r][c]] = null;
                    map[r][c] = i;
                }
            }
            // 이동한 칸이 비었을 경우
            else {
                sharks[i].r = r;
                sharks[i].c = c;
                map[r][c] = i;
            }
        }
    }
 
    private static int fishing() {
 
        // 낚시왕이 있는 열에 있는 상어 중에서 
        for (int i = 1; i <= R; i++) {
            // 땅과 제일 가까운 상어를 잡자.
            if(map[i][king] > 0) {
                int size = sharks[map[i][king]].z; 
                // 잡힌 상어의 정보는 삭제
                sharks[map[i][king]] = null;
                map[i][king] = 0;
                
                return size;
            }
        }
        
        return 0;
    }
 
    static class Shark {
        // 세로, 가로, 속력, 이동방향, 크기
        int r, c, s, d, z;
 
        public Shark(int r, int c, int s, int d, int z) {
            this.r = r;
            this.c = c;
            this.s = s;
            this.d = d;
            this.z = z;
        }
        
    }
}
 
cs


#. Code_v2


상어의 이동을 연산으로



반응형

'PS > Problem_Solving' 카테고리의 다른 글

[BOJ] 14923. 미로 탈출(BFS).java  (0) 2020.12.12
[BOJ] 3055. 탈출(BFS).java  (0) 2020.12.08
[BOJ] 12851. 숨바꼭질2(BFS, DP).java  (0) 2020.12.03
[BOJ] 9019. DSLR(BFS).java  (0) 2020.12.03
[BOJ] 2580. 스도쿠(백트래킹).java  (0) 2020.12.02
댓글
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday