백준문제풀이/구현

20057번 - 마법사 상어와 토네이토

반응형

문제

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

 

20057번: 마법사 상어와 토네이도

마법사 상어가 토네이도를 배웠고, 오늘은 토네이도를 크기가 N×N인 격자로 나누어진 모래밭에서 연습하려고 한다. 위치 (r, c)는 격자의 r행 c열을 의미하고, A[r][c]는 (r, c)에 있는 모래의 양을

www.acmicpc.net


접근방법

1) 접근 사고

태풍에 대한 구조체를 두어 태풍의 이동을 계산하기 쉽게 작성했다. 

1. 태풍이 이동한다.

2. 이동한 위치에 모래가 존재한 지 파악한다. 모래가 있을 경우 태풍의 구조체 중 c.perBoard에 담긴 수치 값을 활용하여 비율에 맞게 모래를 전파한다. 없을 경우 다음 탐색으로 넘어간다.

3. 범위가 초과하여 합계에 더 해줘야 하는지 board에 더해줘야 하는지 구분한다.

4. 이과정을 반복한다.

 

2) 시간 복잡도

O(n ^ 2)

 

3) 실수

1. 태풍의 경로마다 모든 경우를 검색해줘야 하는데 태풍이 꺾이는 점 위치로만 이동을 하여 잘못된 알고리즘 작성

2. perBoard[i][i]같은 인덱스를 잘못 두는 오류(진짜 나 왜 살지??)

 

4) PS

2번 실수 때문에 하루 다 낭비했다. 어금니 꽉 깨물고 디버깅했는데... 디버깅 전에 저런 게 눈에 왜 안 보이는지 너무 슬프다.


정답 코드

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
#include <bits/stdc++.h>
 
using namespace std;
const int MAX = 501;
 
int my[] = {010-1};
int mx[] = {-1010};
 
struct cane {
    int y, x;
    double perboard[5][5];
};
 
struct play {
    int n;
    int sum;
    cane c;
    int board[MAX][MAX];
 
    play(int n) : n(n), sum(0) {}
 
    //입력값, 토네이토로 인해 날아가나는 위치별 비율값 설정
    void init() {
        memset(board, 0sizeof board);
        memset(c.perboard, 0sizeof c.perboard);
 
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                cin >> board[i][j];
            }
        }
 
        c.y = n / 2;
        c.x = n / 2;
        c.perboard[0][2= 0.02;
        c.perboard[1][1= 0.1, c.perboard[1][2= 0.07, c.perboard[1][3= 0.01;
        c.perboard[2][0= 0.05, c.perboard[2][1= 0.55;
        c.perboard[3][1= 0.1, c.perboard[3][2= 0.07, c.perboard[3][3= 0.01;
        c.perboard[4][2= 0.02;
    }
 
    //범위 초과 학인 함수
    bool isValid(int y, int x) {
        return (y >= 0 && y < n && x >= 0 && x < n);
    }
 
    //태풍을 이동시키면서 비율에 맞게 모래를 뿌리는 함수
    void moveCane() {
        int s = 1, dir = 0;
        while (1) {
            for (int i = 0; i < 2; i++) {
                for (int j = 0; j < s; j++) {
                    if (c.y == 0 && c.x == 0) {
                        return;
                    }
                    c.y += my[dir];
                    c.x += mx[dir];
 
                    int curSand = board[c.y][c.x];
                    board[c.y][c.x] = 0;
                    if (curSand == 0)
                        continue;
 
                    for (int i = -2; i <= 2; i++) {
                        for (int j = -2; j <= 2; j++) {
                            double curPercent = c.perboard[i + 2][j + 2];
 
                            int moveSand;
                            //알파의 범위는 먼지가 날리가 남은 만큼이다.
                            if (curPercent >= 0.55) {
                                moveSand = curSand
                                        - floor(curSand * 0.02* 2
                                        - floor(curSand * 0.07* 2
                                        - floor(curSand * 0.10* 2
                                        - floor(curSand * 0.01* 2
                                        - floor(curSand * 0.05);
                            } else {
                                moveSand = floor(curSand * curPercent);
                            }
 
                            int nextY = c.y + i;
                            int nextX = c.x + j;
                            //범위를 초과해 정답에 더해야 하는경우
                            if (!isValid(nextY, nextX)) {
                                sum += moveSand;
                            } else
                                board[nextY][nextX] += moveSand;
                        }
                    }
                }
                dir++;
                if (dir == 4)
                    dir = 0;
                rotateCane();
            }
            s++;
        }
    }
 
    //태풍을 회전시키는 함수
    void rotateCane() {
        double tmpboard[5][5];
        memcpy(tmpboard, c.perboard, sizeof tmpboard);
        for (int i = 0; i < 5; i++) {
            for (int j = 0; j < 5; j++) {
                c.perboard[5 - j - 1][i] = tmpboard[i][j];
            }
        }
    }
 
    //디버깅용
    void printBoard() {
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                cout << board[i][j] << " ";
            }
            cout << "\n";
        }
        cout << "==============" << "\n";
    }
};
 
int main() {
    int n;
    cin >> n;
    play op(n);
    op.init();
    op.moveCane();
    cout << op.sum << "\n";
}
cs
반응형

'백준문제풀이 > 구현' 카테고리의 다른 글

12100번-2048(easy)  (0) 2021.10.01
20058번-마법사 상어와 파이어스톰  (0) 2021.09.28
20055번-컨베이어 벨트 위의 로봇  (0) 2021.09.25
19238번-스타트택시  (0) 2021.09.25
19237번-어른 상어  (0) 2021.09.24