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

 

14499번: 주사위 굴리기

첫째 줄에 지도의 세로 크기 N, 가로 크기 M (1 ≤ N, M ≤ 20), 주사위를 놓은 곳의 좌표 x y(0 ≤ x ≤ N-1, 0 ≤ y ≤ M-1), 그리고 명령의 개수 K (1 ≤ K ≤ 1,000)가 주어진다. 둘째 줄부터 N개의 줄에 지도

www.acmicpc.net

사실 주사위가 이동하는 거만 잘 처리하면 쉬운문제이다.

그거빼고 할게없는 문제.

코드의 대부분이 주사위를 굴린 뒤의 상태이니 말 다했다.

면을 복사하는것과 출력은 매우쉽다.

 

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
#include <iostream>
using namespace std;
int N, M, x, y, K;
int MAP[20][20];
int oper[1001];
int num_dice[7= { 00,0,0,0,0,0 };
// 1    2    3        4    5      6 
// 윗면 앞면 오른쪽면 뒷면 왼쪽면 바닥면
int dice[7]=0,1,5,3,2,4,6 };
int dx[5= { 00,0,-1,1 };
int dy[5= { 01,-1,0,0 };
void oper_1() {
    int temp1 = dice[1]; // 윗면
    int temp2 = dice[3]; // 오른쪽면
    int temp3 = dice[5]; // 왼쪽면
    int temp4 = dice[6]; // 바닥면
    dice[1= temp3;
    dice[3= temp1;
    dice[5= temp4;
    dice[6= temp2;
}
void oper_2() {
    int temp1 = dice[1]; // 윗면
    int temp2 = dice[3]; // 오른쪽면
    int temp3 = dice[5]; // 왼쪽면
    int temp4 = dice[6]; // 바닥면
    dice[1= temp2;
    dice[3= temp4;
    dice[5= temp1;
    dice[6= temp3;
}
void oper_3() {
    int temp1 = dice[1]; // 위
    int temp2 = dice[2]; // 앞
    int temp3 = dice[6]; // 바닥
    int temp4 = dice[4]; // 뒷면
    dice[1= temp2;
    dice[2= temp3;
    dice[6= temp4;
    dice[4= temp1;
}
void oper_4() {
    int temp1 = dice[1]; // 위
    int temp2 = dice[2]; // 앞
    int temp3 = dice[6]; // 바닥
    int temp4 = dice[4]; // 뒷면
    dice[1= temp4;
    dice[2= temp1;
    dice[6= temp2;
    dice[4= temp3;
}
void find() {
    for (int i = 1; i <= K; i++) {
        int next_x = x + dx[oper[i]];
        int next_y = y + dy[oper[i]];
        if (next_x >= 0 && next_x <= N - 1 && next_y >= 0 && next_y <= M - 1) {
            //cout << "oper : "<< oper[i] << endl;
            if (oper[i] == 1)
                oper_1();
            else if (oper[i] == 2)
                oper_2();
            else if (oper[i] == 3)
                oper_3();
            else if (oper[i] == 4)
                oper_4();
            if (MAP[next_x][next_y] == 0) {
                MAP[next_x][next_y] = num_dice[dice[6]];
                cout << num_dice[dice[1]] << "\n";
            }
            else {
                num_dice[dice[6]] = MAP[next_x][next_y];
                MAP[next_x][next_y] = 0;
                cout << num_dice[dice[1]] << "\n";
            }
            x = next_x;
            y = next_y;
        }
        else
            continue;
    }
}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin >> N >> M;
    cin >> x >> y >> K;
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < M; j++) {
            cin >> MAP[i][j];
        }
    }
    for (int i = 1; i <= K; i++)
        cin >> oper[i];
 
    find();
}
cs

'BAEKJOON ONLINE JUDGE' 카테고리의 다른 글

[백준 20061] 모노미노도미노 2 (C++)  (0) 2021.08.23
[백준 21609] 상어 중학교 (C++)  (0) 2021.08.22
[백준 3190] 뱀 (C++)  (0) 2021.08.21
[백준 1092] 배 (C++)  (0) 2021.08.21
[백준 19237] 어른 상어 (C++)  (0) 2021.08.21

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

 

3190번: 뱀

 'Dummy' 라는 도스게임이 있다. 이 게임에는 뱀이 나와서 기어다니는데, 사과를 먹으면 뱀 길이가 늘어난다. 뱀이 이리저리 기어다니다가 벽 또는 자기자신의 몸과 부딪히면 게임이 끝난다. 게임

www.acmicpc.net

옛날에 풀었던 문제이다.

뱀의 상태만 잘 처리하면 쉬운문제이다.

풀이는 다음과 같다.

snake의 좌표는 queue로 관리한다.

사실 queue로 뱀의 좌표를 관리하면 쉬운문제이다.

코드는 다음과 같다.

 

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
#include <iostream>
#include <vector>
#include <utility>
#include <queue>
#define MAX 100+1
using namespace std;
int N,K,L;
int map[MAX][MAX];
vector<pair<intchar>> vec;
queue<pair<intint>> snake;
// 오른쪽 아래 왼쪽 위
int dx[4= { 0,1,0,-1 };
int dy[4= { 1,0,-1,0 };
void find() {
    int state = 0;
    int x = 1;
    int y = 1;
    map[x][y] = 1;
    int time = 0;
    int index = 0;
    snake.push(make_pair(x, y));
    while (1) {
        if (!vec.empty() && time == vec[index].first) {
            if (vec[index].second == 'L') {
                state = state - 1;
                if (state == -1) {
                    state = 3;
                }
            }
            if (vec[index].second == 'D') {
                state = state + 1;
                if (state == 4) {
                    state = 0;
                }
            }
            vec.erase(vec.begin());
        }
        time++;
        int next_x = x + dx[state];
        int next_y = y + dy[state];
        if (next_x >= 1 && next_x <= N && next_y >= 1 && next_y <= N) {
            if (map[next_x][next_y] == 0) {
                map[next_x][next_y] = 1;
                map[snake.front().first][snake.front().second] = 0;
                snake.pop();
                snake.push(make_pair(next_x, next_y));
                x = next_x;
                y = next_y;
            }
            else if (map[next_x][next_y] == 1)
                break;
            else if (map[next_x][next_y] == 2) {
                snake.push(make_pair(next_x, next_y));
                map[next_x][next_y] = 1;
                x = next_x;
                y = next_y;
            }
        }
        else
            break;
    }
    cout << time << endl;
}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin >> N;
    cin >> K;
    for (int i = 0; i < K; i++) {
        int x, y;
        cin >> x >> y;
        map[x][y] = 2;
    }
    cin >> L;
    for (int i = 0; i < L; i++) {
        int x;
        char y;
        cin >> x >> y;
        vec.push_back(make_pair(x, y));
    }
    find();
}
cs

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

 

1092번: 배

첫째 줄에 N이 주어진다. N은 50보다 작거나 같은 자연수이다. 둘째 줄에는 각 크레인의 무게 제한이 주어진다. 이 값은 1,000,000보다 작거나 같다. 셋째 줄에는 박스의 수 M이 주어진다. M은 10,000보

www.acmicpc.net

그리디 알고리즘 문제이다.

그리디가 약하다고 생각해서 풀어본 문제

결론적으로 두번 시간초과가 발생ㅋㅋㅋㅋ

풀이는 다음과 같다.

무거운 거를 옮기는 크레인들은 아래에있는 것들도 옮길 수 있다 라는 사실을 확인

그러면 내림차순으로 정렬 후에 각 크레인이 옮길 수 있는 것중에 제일 무거운거부터 이동하면 된다고 생각했다.
코드는 다음과 같다.

 

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
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int N, M;
vector<int> Crain; // 시작
vector<int> weight;
bool cmp(const int& a, const int& b) {
    return a > b;
}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin >> N;
    for (int i = 0; i < N; i++) {
        int num;
        cin >> num;
        Crain.push_back(num);
    }
    cin >> M;
    for (int i = 0; i < M; i++) {
        int num;
        cin >> num;
        weight.push_back(num);
    }
    sort(Crain.begin(), Crain.end(), cmp);
    sort(weight.begin(), weight.end(), cmp);
    int cnt = 0;
    if (weight[0> Crain[0]) {
        cout << -1 << endl;
        return 0;
    }
    int size = M;
    while (!weight.empty()) {
        int index = 0;
        for (int i = 0; i < size; i++) {
            if (index == N) {
                break;
            }
            if (Crain[index] >= weight[i]) {
                index++;
                size--;
                weight.erase(weight.begin() + i);
                i = i - 1;
            }
        }
        cnt++;
    }
    cout << cnt << endl;
 
 
}
cs

'BAEKJOON ONLINE JUDGE' 카테고리의 다른 글

[백준 14499] 주사위 굴리기 (C++)  (0) 2021.08.21
[백준 3190] 뱀 (C++)  (0) 2021.08.21
[백준 19237] 어른 상어 (C++)  (0) 2021.08.21
[백준 17090] 미로 탈출하기 (C++)  (0) 2021.08.20
[백준 14890] 경사로 (C++)  (0) 2021.08.20

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

 

19237번: 어른 상어

첫 줄에는 N, M, k가 주어진다. (2 ≤ N ≤ 20, 2 ≤ M ≤ N2, 1 ≤ k ≤ 1,000) 그 다음 줄부터 N개의 줄에 걸쳐 격자의 모습이 주어진다. 0은 빈칸이고, 0이 아닌 수 x는 x번 상어가 들어있는 칸을 의미

www.acmicpc.net

바보같이 3번 틀린 문제, M을 N으로 쓰는..바보같은 짓을 했다.

코드의 진행과정은 다음과 같다.

MAP과 Shark 구조체 선언

MAP에는 smell_count와 size 즉 상어의 크기,

Shark에는 x, y, dir, 우선순위 방향, 생사 유무가 저장되어있다.

input에서부터 고민하게 되는 문제이다.
N,M,K를 입력 받은 후 MAP의 정보를 입력 받는다. 이때 상어의 위치도 같이 저장.
그 다음 상어의 방향을 입력 받을때는 상어의 생사 유무도 입력받는다.
그 다음은 상어의 방향 우선순위이다, 방향은 Shark 구조체 안에 [5][5] 배열을 넣어줘서 사용한다.
solve 함수는 4가지 함수로 돌아간다.
첫번째 move 함수,
상어가 움직일 수 있는 위치를 확인한다. 그리고 shark_info 배열에 바뀐 위치와 방향을 저장
이때 map은 건드리지않는다.
두번째 kill_and_move함수

상어가 맵에서 움직이는 함수이다. 움직일때 1번부터 순서대로 이동하므로, 만약 이동하는 칸에 상어가 있으면,
그 상어는 숫자가 작은 함수 이므로, 늦게 움직이는 상어는 죽는다.
세번째는 smell_processing함수

상어의 냄새를 처리 하는 함수, 처음에는 bfs로 냄새의 위치를 탐색 할려 했지만, 맵이 20*20이므로, 그냥 모두 확인
냄새를 다 -- 해준다, 그리고 이동한 곳의 냄새는 K로 초기화한다,
네번째는 모두 false인지 check하는 함수이다.
여기서 M을 N으로 써서 4번틀림 ㅇㅇ

전체 코드는 다음과 같다.

 

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
142
143
144
145
146
147
148
149
150
151
152
#include <iostream>
#include <deque>
#include <utility>
#include <vector>
#include <queue>
using namespace std;
struct MAP {
    int smell_count;
    int size;
};
struct Shark {
    int x, y;
    int dir;
    int prior_dir[5][5];
    bool alive;
};
// 위 아래 왼쪽 오른쪽
int dx[5= { 0,-1,1,0,0 };
int dy[5= { 0,0,0,-1,1 };
// 변수들
int N, M, K;
Shark SHARK_INFO[401];
MAP MAP_INFO[21][21];
// 냄새가 있는 좌표 관리
bool check_range(int& next_x, int& next_y) {
    if (next_x >= 1 && next_y >= 1 && next_x <= N && next_y <= N)
        return true;
    else
        return false;
}
bool check_shark() {
    for (int i = 2; i <= M; i++) {
        if (SHARK_INFO[i].alive == true) {
            return false;
        }
    }
    return true;
}
void smell_Processing() {
    for (int i = 1; i <= N; i++) {
        for (int j = 1; j <= N; j++) {
            if (MAP_INFO[i][j].smell_count != 0) {
                MAP_INFO[i][j].smell_count--;
                if (MAP_INFO[i][j].smell_count == 0) {
                    MAP_INFO[i][j].size = 0;
                }
            }
        }
    }
    for (int i = 1; i <= M; i++) {
        if (SHARK_INFO[i].alive == false)
            continue;
        int x = SHARK_INFO[i].x;
        int y = SHARK_INFO[i].y;
        MAP_INFO[x][y].size = i;
        MAP_INFO[x][y].smell_count = K;
    }
}
void kill_and_move() {
    for (int i = 1; i <= M; i++) {
        if (SHARK_INFO[i].alive == false
            continue;
        int x = SHARK_INFO[i].x;
        int y = SHARK_INFO[i].y;
        //cout << SHARK_INFO[i].x << SHARK_INFO[i].y << endl;
        if (MAP_INFO[x][y].size == 0 || MAP_INFO[x][y].size == i)
            MAP_INFO[x][y].size = i;
        else 
            SHARK_INFO[i].alive = false;
    }
}
void move() {
    for (int i = 1; i <= M; i++) {
        if (SHARK_INFO[i].alive == false)
            continue;
        // 처음에는 우선 순위로 빈칸 이동 확인하기
        int dir = SHARK_INFO[i].dir;
        bool flag = false;
        for (int j = 1; j <= 4; j++) {
            int next_x = SHARK_INFO[i].x + dx[SHARK_INFO[i].prior_dir[dir][j]];
            int next_y = SHARK_INFO[i].y + dy[SHARK_INFO[i].prior_dir[dir][j]];
            if (check_range(next_x, next_y) && MAP_INFO[next_x][next_y].size == 0) {
                SHARK_INFO[i].dir = SHARK_INFO[i].prior_dir[dir][j];
                SHARK_INFO[i].x = next_x;
                SHARK_INFO[i].y = next_y;
                flag = true;
                break;
            }
        }
        if (flag == true)
            continue;
        // 자기 냄새 칸으로 우선 순위 지켜서 이동
        for (int j = 1; j <= 4; j++) {
            int next_x = SHARK_INFO[i].x + dx[SHARK_INFO[i].prior_dir[dir][j]];
            int next_y = SHARK_INFO[i].y + dy[SHARK_INFO[i].prior_dir[dir][j]];
            if (check_range(next_x, next_y) && MAP_INFO[next_x][next_y].size == i) {
                SHARK_INFO[i].dir = SHARK_INFO[i].prior_dir[dir][j];
                SHARK_INFO[i].x = next_x;
                SHARK_INFO[i].y = next_y;
                break;
            }
        }
    }
}
void solve() {
    // 이동 할 칸 확인하기
    int day = 0;
    while (day < 1000){
        day++;
        move();
        kill_and_move();
        smell_Processing();
        if (check_shark() == true) {
            cout << day << endl;
            return;
        }
    }
    cout << -1 << endl;
}
void input() {
    cin >> N >> M >> K;
    for (int i = 1; i <= N; i++) {
        for (int j = 1; j <= N; j++) {
            cin >> MAP_INFO[i][j].size;
            if (MAP_INFO[i][j].size != 0) {
                SHARK_INFO[MAP_INFO[i][j].size].x = i;
                SHARK_INFO[MAP_INFO[i][j].size].y = j;
                MAP_INFO[i][j].smell_count = K;
            }
        }
    }
    for (int i = 1; i <= M; i++) {
        cin >> SHARK_INFO[i].dir;
        SHARK_INFO[i].alive = true;
    }
    for (int i = 1; i <= M; i++) {
        for (int j = 1; j <= 4; j++) {
            for (int k = 1; k <= 4; k++) {
                cin >> SHARK_INFO[i].prior_dir[j][k];
            }
        }
    }
}
void init() {
    ios::sync_with_stdio(false);
    cin.tie(0);
}
int main() {
    init();
    input();
    solve();
}
cs

'BAEKJOON ONLINE JUDGE' 카테고리의 다른 글

[백준 3190] 뱀 (C++)  (0) 2021.08.21
[백준 1092] 배 (C++)  (0) 2021.08.21
[백준 17090] 미로 탈출하기 (C++)  (0) 2021.08.20
[백준 14890] 경사로 (C++)  (0) 2021.08.20
[백준 19236] 청소년 상어 (C++)  (0) 2021.08.19

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

 

17090번: 미로 탈출하기

크기가 N×M인 미로가 있고, 미로는 크기가 1×1인 칸으로 나누어져 있다. 미로의 각 칸에는 문자가 하나 적혀있는데, 적혀있는 문자에 따라서 다른 칸으로 이동할 수 있다. 어떤 칸(r, c)에 적힌 문

www.acmicpc.net

시간을 최대한 쾌적하게 사용해야한다.

총 4번의 시도 끝에 성공..

처음 방법

그냥 일반적으로 탐색하다가 밖에 나오면 성공!으로 했지만, 실패

두번째는 q_history를 만들어 성공한 경우 탐색한 칸들은 MAP_CHECK배열에 true로 넣어 그 칸에 도착시 자동으로
탈출이 가능하다고 했다. 하지만 또 시간초가

세번재는 q_history를 통해서 탈출하지 못하는 경우도 MAP_CHECK_NOT배열에 true로 전달, 그 칸에 도착시 자동으로
탈출 못하는 하지만 실패
다음 방법은 방문 여부를 확인하는 check배열을 밖으로 빼어 매번 false로 초기화 하는 방식이 아닌, 성공하든 실패하든
check을 false로 만드는 방법 , 즉 이동경로를 확인하는 q_history가 있으므로, 그걸로 false로 초기화, 결과는 성공.
코드는 다음과 같다.

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
#include <iostream>
#include <queue>
using namespace std;
int N, M;
char MAP[501][501];
bool MAP_CHECK[501][501];
bool MAP_CHECK_NOT[501][501];
bool check[501][501= { false };
// U R D L
int dx[4= { -1,0,1,0 };
int dy[4= { 0,1,0,-1 };
int count_res = 0;
void check_clean(int index, queue<pair<int,int>> &q_history) {
    if (index == 0) {
        while (!q_history.empty()) {
            MAP_CHECK_NOT[q_history.front().first][q_history.front().second] = true;
            check[q_history.front().first][q_history.front().second] = false;
            q_history.pop();
        }
    }
    else if (index == 1) {
        while (!q_history.empty()) {
            MAP_CHECK[q_history.front().first][q_history.front().second] = true;
            check[q_history.front().first][q_history.front().second] = false;
            q_history.pop();
        }
    }
}
int dir_check(char c) {
    if (c == 'U')
        return 0;
    else if (c == 'R')
        return 1;
    else if (c == 'D')
        return 2;
    else if (c == 'L')
        return 3;
}
void solve(int x,int y) {
    check[x][y] = true;
    queue<pair<intint>> q;
    queue<pair<intint>> q_history;
    q.push(make_pair(x, y));
    //cout << x << y << endl;
    while (!q.empty()) {
        int prev_x = q.front().first;
        int prev_y = q.front().second;
        int dir = dir_check(MAP[prev_x][prev_y]);
        q_history.push(make_pair(prev_x,prev_y));
        if (MAP_CHECK[prev_x][prev_y] == true) {
            check_clean(1, q_history);
            count_res++;
            return;
        }
        if (MAP_CHECK_NOT[prev_x][prev_y] == true) {
            check_clean(0, q_history);
            return;
        }
        q.pop();
        int next_x = prev_x + dx[dir];
        int next_y = prev_y + dy[dir];
        if (next_x >= 1 && next_y >= 1 && next_x <= N && next_y <= M) {
            if (check[next_x][next_y] == false) {
                check[next_x][next_y] = true;
                q.push(make_pair(next_x, next_y));
            }
            else {
                check_clean(0, q_history);
                return;
            }
        }
        else {
            check_clean(1, q_history);
            count_res++;
            return;
        }
    }
}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin >> N >> M;
    for (int i = 1; i <= N; i++)
        for (int j = 1; j <= M; j++)
            cin >> MAP[i][j];
    for (int i = 1; i <= N; i++) {
        for (int j = 1; j <= M; j++) {
            solve(i, j);
        }
    }
    cout << count_res << endl;
}
cs

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

 

14890번: 경사로

첫째 줄에 N (2 ≤ N ≤ 100)과 L (1 ≤ L ≤ N)이 주어진다. 둘째 줄부터 N개의 줄에 지도가 주어진다. 각 칸의 높이는 10보다 작거나 같은 자연수이다.

www.acmicpc.net

골드3 문제지만 생각만 잘 하면 30분이면 해결가능하다.

시간도 2초로 매우 넉넉하다..

코드는 매우 간단하다.

row와 col를 벡터로 선언하여 전달한다. 각 downhill이 가능한지 check하기 위해 복사하여 넘기는 방식으로 하였다.
Downhill_Discrimination 함수에서는 다음과 같은 과정으로 경사로가 가능한지 check한다.

bool check[100]을 선언한다.
L=2일때 앞뒤로 경사로가 겹치는 경우, 즉 내려갔다 올라가는 경우 평지가 4가 필요한데 , 4보다 적은 것을 check하기 위한것이다. 

이때 내려가는 부분먼저 check한다. 높이가 2이상 차이나면 return;

line[i] - line[i+1]이 1, 즉 내려가는 방향이면 둘 수 있는지 확인한다.
확인 방식은 L개만큼 연속된 평지가 있어야 하므로 첫번째 IF문은 조건이 i+count < N 이다. index안에서만 해결
그 다음은 평지인지와 check[i+count]가 false인지 check한다.
지금 생각하니 내리막에서는 딱히 check를 할 필요가 없을거 가다.

 

오르막은 똑같다, 이것은 N-1부터 1까지 check한다.
논리는 모두 같다. 

전체코드는 다음과 같다.

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
// 경사로
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
struct check_hill {
    int index;
    int up_down; // -1 이면 올라가는 방향 , 1 이면 내려가는 방향, 0 
};
int N, L;
int MAP[100][100];
int count_res = 0;
void Downhill_Discrimination(vector<int>& line) {
    // 경우의 수
    // 우선 높이 차이가 2이면 return
    bool check[100= { false };
    // 내려가는거 체크
    for (int i = 0; i < N - 1; i++) {
        if (abs(line[i] - line[i + 1]) >= 2)
            return;
        if (line[i] - line[i + 1== 1) { // 내려 가는 방향이면
            int level = line[i + 1];
            for (int count = 1; count <= L; count++) {
                if (i + count < N) {
                    if (level == line[i + count] && check[i+count] == false) {
                        check[i+count] = true;
                    }
                    else {
                        return;
                    }
                }
                else {
                    return;
                }
            }
        }
    }
    // 올라가는거 체크
    for (int i = N - 1; i > 0; i--) {
        if (abs(line[i] - line[i - 1]) >= 2)
            return;
        if (line[i] - line[i - 1== 1) {
            int level = line[i - 1];
            for (int count = 1; count <= L; count++) {
                if (i - count > -1) {
                    if (level == line[i - count] && check[i - count] == false) {
                        check[i - count] = true;
                    }
                    else {
                        return;
                    }
                }
                else {
                    return;
                }
            }
        }
    }
    count_res++;
}
void solve() {
    // 행열 처리
    for (int i = 0; i < N; i++) {
        vector<int> row;
        vector<int> col;
        for (int j = 0; j < N; j++) {
            row.push_back(MAP[i][j]);
            col.push_back(MAP[j][i]);
        }
        Downhill_Discrimination(row);
        Downhill_Discrimination(col);
    }
    cout << count_res << endl;
}
void input() {
    cin >> N >> L;
    for (int i = 0; i < N; i++)
        for (int j = 0; j < N; j++)
            cin >> MAP[i][j];
}
void init() {
    cin.tie(0)->sync_with_stdio(false);
}
int main() {
    init();
    input();
    solve();
}
cs

문제

아기 상어가 성장해 청소년 상어가 되었다.

4×4크기의 공간이 있고, 크기가 1×1인 정사각형 칸으로 나누어져 있다. 공간의 각 칸은 (x, y)와 같이 표현하며, x는 행의 번호, y는 열의 번호이다. 한 칸에는 물고기가 한 마리 존재한다. 각 물고기는 번호와 방향을 가지고 있다. 번호는 1보다 크거나 같고, 16보다 작거나 같은 자연수이며, 두 물고기가 같은 번호를 갖는 경우는 없다. 방향은 8가지 방향(상하좌우, 대각선) 중 하나이다.

오늘은 청소년 상어가 이 공간에 들어가 물고기를 먹으려고 한다. 청소년 상어는 (0, 0)에 있는 물고기를 먹고, (0, 0)에 들어가게 된다. 상어의 방향은 (0, 0)에 있던 물고기의 방향과 같다. 이후 물고기가 이동한다.

물고기는 번호가 작은 물고기부터 순서대로 이동한다. 물고기는 한 칸을 이동할 수 있고, 이동할 수 있는 칸은 빈 칸과 다른 물고기가 있는 칸, 이동할 수 없는 칸은 상어가 있거나, 공간의 경계를 넘는 칸이다. 각 물고기는 방향이 이동할 수 있는 칸을 향할 때까지 방향을 45도 반시계 회전시킨다. 만약, 이동할 수 있는 칸이 없으면 이동을 하지 않는다. 그 외의 경우에는 그 칸으로 이동을 한다. 물고기가 다른 물고기가 있는 칸으로 이동할 때는 서로의 위치를 바꾸는 방식으로 이동한다.

물고기의 이동이 모두 끝나면 상어가 이동한다. 상어는 방향에 있는 칸으로 이동할 수 있는데, 한 번에 여러 개의 칸을 이동할 수 있다. 상어가 물고기가 있는 칸으로 이동했다면, 그 칸에 있는 물고기를 먹고, 그 물고기의 방향을 가지게 된다. 이동하는 중에 지나가는 칸에 있는 물고기는 먹지 않는다. 물고기가 없는 칸으로는 이동할 수 없다. 상어가 이동할 수 있는 칸이 없으면 공간에서 벗어나 집으로 간다. 상어가 이동한 후에는 다시 물고기가 이동하며, 이후 이 과정이 계속해서 반복된다.

<그림 1>

<그림 1>은 청소년 상어가 공간에 들어가기 전 초기 상태이다. 상어가 공간에 들어가면 (0, 0)에 있는 7번 물고기를 먹고, 상어의 방향은 ↘이 된다. <그림 2>는 상어가 들어간 직후의 상태를 나타낸다.

<그림 2>

이제 물고기가 이동해야 한다. 1번 물고기의 방향은 ↗이다. ↗ 방향에는 칸이 있고, 15번 물고기가 들어있다. 물고기가 있는 칸으로 이동할 때는 그 칸에 있는 물고기와 위치를 서로 바꿔야 한다. 따라서, 1번 물고기가 이동을 마치면 <그림 3>과 같아진다.

<그림 3>

2번 물고기의 방향은 ←인데, 그 방향에는 상어가 있으니 이동할 수 없다. 방향을 45도 반시계 회전을 하면 ↙가 되고, 이 칸에는 3번 물고기가 있다. 물고기가 있는 칸이니 서로 위치를 바꾸고, <그림 4>와 같아지게 된다.

<그림 4>

3번 물고기의 방향은 ↑이고, 존재하지 않는 칸이다. 45도 반시계 회전을 한 방향 ↖도 존재하지 않으니, 다시 회전을 한다. ← 방향에는 상어가 있으니 또 회전을 해야 한다. ↙ 방향에는 2번 물고기가 있으니 서로의 위치를 교환하면 된다. 이런 식으로 모든 물고기가 이동하면 <그림 5>와 같아진다.

<그림 5>

물고기가 모두 이동했으니 이제 상어가 이동할 순서이다. 상어의 방향은 ↘이고, 이동할 수 있는 칸은 12번 물고기가 있는 칸, 15번 물고기가 있는 칸, 8번 물고기가 있는 칸 중에 하나이다. 만약, 8번 물고기가 있는 칸으로 이동하면, <그림 6>과 같아지게 된다.

<그림 6>

상어가 먹을 수 있는 물고기 번호의 합의 최댓값을 구해보자.

입력

첫째 줄부터 4개의 줄에 각 칸의 들어있는 물고기의 정보가 1번 행부터 순서대로 주어진다. 물고기의 정보는 두 정수 ai, bi로 이루어져 있고, ai는 물고기의 번호, bi는 방향을 의미한다. 방향 bi는 8보다 작거나 같은 자연수를 의미하고, 1부터 순서대로 ↑, ↖, ←, ↙, ↓, ↘, →, ↗ 를 의미한다.

출력

상어가 먹을 수 있는 물고기 번호의 합의 최댓값을 출력한다.

예제 입력 1

7 6 2 3 15 6 9 8
3 1 1 8 14 7 10 1
6 1 13 6 4 3 11 4
16 1 8 7 5 2 12 2

 

예제 출력 1

33

예제 입력 2

16 7 1 4 4 3 12 8
14 7 7 6 3 4 10 2
5 2 15 2 8 3 6 4
11 8 2 4 13 5 9 4

예제 출력 2

43

예제 입력 3

12 6 14 5 4 5 6 7
15 1 11 7 3 7 7 5
10 3 8 3 16 6 1 1
5 8 2 7 13 6 9 2

예제 출력 3

76

예제 입력 4

2 6 10 8 6 7 9 4
1 7 16 6 4 2 5 8
3 7 8 6 7 6 14 8
12 7 15 4 11 3 13 3

예제 출력 4

39

 

풀이

문제를 읽자마자 재귀의 느낌이 들었다.
처음에 Fish_list와 Fish_map을 이용하여 초기상태를 저장하였다.
그 다음 solve함수에 전달, 맨 처음 한 일은 Fish_list에 따라 Fish_map을 초기화. 이렇게 한 이유는.. 재귀 할 때마다 
이유를 모르겟는 오류가 발생 ㅠ
그다음 Shark_state에 들어있는 값을 이용해 생선을 먹방...이때 상어가 이동하는데 거기가 0이면 return해버린다
먹은거를 정리 하고 총 16마리니깐 for문을 16번한다. 이때 size가 0, 이미먹힌거는 continue한다.
움직일 수 있는지 체크, 총 8번 for문을 돌린다. 이떄 0이냐, 0이아니냐에 따라 조건을 나눈다.. 
다시보니 조건을 나눌필요가 딱히 없을거같다.
dir은 +1씩하며 체크한다. 모두 이동이 끝나면! 상어 이동
상어가 이동하기 위해 next_x, next_y를 선언 및 상어위치 전달.
방향으로 이동하는데 이때 맵 범위 안이면 이동한다. 물고기 있는지는 위쪽에서 체크..
그다음은 뭐 재귀문을 계속돌린다..

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
// 청소년 상어
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
struct Fish
{
    int x, y;
    int size;
    int dir;
};
bool cmp(const Fish& a, const Fish& b) {
    return a.size < b.size;
}
int MAX_RES = 0;
// ↑, ↖, ←, ↙, ↓, ↘, →, ↗
int dx[9= { 0-1,-1,0,1,1,1,0,-1 };
int dy[9= { 00,-1,-1,-1,0,1,1,1 };
void solve(int Fish_Map[5][5], vector<Fish> Fish_list, Fish Shark_state, int total_size) {
    for (int i = 1; i <= 4; i++)
        for (int j = 1; j <= 4; j++)
            Fish_Map[i][j] = 0;
    for (int i = 1; i <= 16;i++) {
        if (Fish_list[i].size == 0)continue;
        Fish_Map[Fish_list[i].x][Fish_list[i].y] = Fish_list[i].size;
    }
    if (Fish_Map[Shark_state.x][Shark_state.y] == 0)
        return;
    // Shark_state에 size 할당 및 방향 choose
    Shark_state.size = Fish_Map[Shark_state.x][Shark_state.y];
    Shark_state.dir = Fish_list[Shark_state.size].dir;
    // 먹은거 정리
    Fish_Map[Shark_state.x][Shark_state.y] = 0;
    Fish_list[Shark_state.size].size = 0;
    total_size += Shark_state.size;
    MAX_RES = max(total_size, MAX_RES);
    // 물고기 이동
    for (int i = 1; i <= 16; i++) {
        if (Fish_list[i].size == 0// 이미 상어가 먹어버린 물고기
            continue;
        for (int j = 1; j <= 8; j++) {
            int next_x = Fish_list[i].x + dx[Fish_list[i].dir];
            int next_y = Fish_list[i].y + dy[Fish_list[i].dir];
            // 범위 안 인지 체크
            if (next_x >= 1 && next_y >= 1 && next_x <= 4 && next_y <= 4) {
                // 다음 칸이 상어가 있는지 체크
                if (Shark_state.x != next_x || Shark_state.y != next_y) {
                    // 다음 칸이 빈칸 일 경우
                    if (Fish_Map[next_x][next_y] == 0) {
                        Fish_Map[Fish_list[i].x][Fish_list[i].y] = 0;
                        Fish_list[i].x = next_x;
                        Fish_list[i].y = next_y;
                        Fish_Map[next_x][next_y] = Fish_list[i].size;
                        break;
                    }
                    // 다음 칸이 빈칸이 아닌 경우
                    else {
                        int next_site_fish_size = Fish_Map[next_x][next_y];
                        Fish_list[next_site_fish_size].x = Fish_list[i].x;
                        Fish_list[next_site_fish_size].y = Fish_list[i].y;
                        Fish_list[i].x = next_x;
                        Fish_list[i].y = next_y;
                        Fish_Map[Fish_list[next_site_fish_size].x][Fish_list[next_site_fish_size].y] = next_site_fish_size;
                        Fish_Map[Fish_list[i].x][Fish_list[i].y] = Fish_list[i].size;
                        break;
                    }
                }
            }
            Fish_list[i].dir += 1;
            if (Fish_list[i].dir == 9
                Fish_list[i].dir = 1;
        }
    }
    int next_x = Shark_state.x;
    int next_y = Shark_state.y;
    while (1) {
        next_x = next_x + dx[Shark_state.dir];
        next_y = next_y + dy[Shark_state.dir];
        if (next_x >= 1 && next_y >= 1 && next_x <= 4 && next_y <= 4) {
            Fish temp;
            temp.x = next_x; temp.y = next_y; temp.size = 0; temp.dir = -1;
            solve(Fish_Map, Fish_list, temp, total_size);
        }
        else
            break;
    }
}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    vector<Fish> Fish_list;
    Fish_list.push_back({ 0000 });
    int Fish_Map[5][5];
    for (int i = 1; i <= 4; i++) {
        for (int j = 1; j <= 4; j++) {
            int size, dir;
            cin >> size >> dir;
            Fish_list.push_back({ i,j,size,dir });
            Fish_Map[i][j] = size;
        }
    }
    sort(Fish_list.begin(), Fish_list.end(),cmp);
    solve(Fish_Map, Fish_list, { 1,1,0,-1 }, 0);
    cout << MAX_RES << endl;
}
cs

 

문제

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

토네이도를 시전하면 격자의 가운데 칸부터 토네이도의 이동이 시작된다. 토네이도는 한 번에 한 칸 이동한다. 다음은 N = 7인 경우 토네이도의 이동이다.

토네이도가 한 칸 이동할 때마다 모래는 다음과 같이 일정한 비율로 흩날리게 된다.

토네이도가 x에서 y로 이동하면, y의 모든 모래가 비율과 α가 적혀있는 칸으로 이동한다. 비율이 적혀있는 칸으로 이동하는 모래의 양은 y에 있는 모래의 해당 비율만큼이고, 계산에서 소수점 아래는 버린다. α로 이동하는 모래의 양은 비율이 적혀있는 칸으로 이동하지 않은 남은 모래의 양과 같다. 모래가 이미 있는 칸으로 모래가 이동하면, 모래의 양은 더해진다. 위의 그림은 토네이도가 왼쪽으로 이동할 때이고, 다른 방향으로 이동하는 경우는 위의 그림을 해당 방향으로 회전하면 된다.

토네이도는 (1, 1)까지 이동한 뒤 소멸한다. 모래가 격자의 밖으로 이동할 수도 있다. 토네이도가 소멸되었을 때, 격자의 밖으로 나간 모래의 양을 구해보자.

입력

첫째 줄에 격자의 크기 N이 주어진다. 둘째 줄부터 N개의 줄에는 격자의 각 칸에 있는 모래가 주어진다. r번째 줄에서 c번째 주어지는 정수는 A[r][c] 이다.

출력

격자의 밖으로 나간 모래의 양을 출력한다.

제한

  • 3 ≤ N ≤ 499
  • N은 홀수
  • 0 ≤ A[r][c] ≤ 1,000
  • 가운데 칸에 있는 모래의 양은 0

예제 입력 1

5
0 0 0 0 0
0 0 0 0 0
0 10 0 0 0
0 0 0 0 0
0 0 0 0 0

예제 출력 1

10

예제 입력 2

5
0 0 0 0 0
0 0 0 0 0
0 100 0 0 0
0 0 0 0 0
0 0 0 0 0

예제 출력 2

85

예제 입력 3

7
1 2 3 4 5 6 7
1 2 3 4 5 6 7
1 2 3 4 5 6 7
1 2 3 0 5 6 7
1 2 3 4 5 6 7
1 2 3 4 5 6 7
1 2 3 4 5 6 7

예제 출력 3

139

예제 입력 4

5
100 200 300 400 200
300 243 432 334 555
999 111 0 999 333
888 777 222 333 900
100 200 300 400 500

예제 출력 4

7501

예제 입력 5

5
0 0 100 0 0
0 0 100 0 0
0 0 0 0 0
0 0 100 0 0
0 0 100 0 0

예제 출력 5

283

예제 입력 6

9
193 483 223 482 858 274 847 283 748
484 273 585 868 271 444 584 293 858
828 384 382 818 347 858 293 999 727
818 384 727 373 636 141 234 589 991
913 564 555 827 0 999 123 123 123
321 321 321 983 982 981 983 980 990
908 105 270 173 147 148 850 992 113
943 923 982 981 223 131 222 913 562
752 572 719 590 551 179 141 137 731

22961

 

풀이

이동하는 경로만 간단하게 계산하면 쉬운 문제이다.

대충 이동경로를 생각해보자.

처음에는

N = 5 인 맵을 생각해보자 

← 1번,  ↓ 1번

그 다음에는

→ 2번,  ↑ 2번

그 다음에는

← 3번,  ↓ 3번

그 다음에는

→ 4번,  ↑ 4번 ← 4번 끝

이정도 쓰면 눈치 챌듯? 할거같네요. 방향은 반시계로 돌아가며, 1, 2, 3 이 두번 반복, 마지막 N-1번 이동시에는 연속3번 이동

이 규칙을 이해하면된다.

그리고 먼지 뿌리는건 현재 방향에서 -1, +1 방향으로 먼지를 뿌리고 남은 것을 알파에 뿌린다.

이떄 알파에 들어갈 먼지를 계산할때 유의 해야한다.. 

알파에 들어갈 먼지양을 계산시 int(이동하는 먼지양 * 0.01) 필수다. int *******

함수 리스트

void init();  // ios::~~`
void input(); // inpurt
void Move_Tornado(); // 토네이도를 계산하기 시작하는 함수
void move(); // 이동하는 것을 계산
void dust(); // 먼지가 퍼지는 것을 계산
bool check_map_range(int& next_x, int& next_y); // 맵 범위가 맞는지 계산

코드는 다음과 같다. 

 

 

 

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
142
143
144
145
146
147
148
149
150
151
#include <iostream>
#include <iomanip>
#define MAX 1000+1
using namespace std;
int N;
int A[MAX][MAX];
// 0    1      2      3
// 왼쪽 아래쪽 오른쪽 위쪽
int dx[4= { 0,1,0,-1 };
int dy[4= { -1,0,1,0 };
int Tornado_x; int Tornado_y;
int prev_x; int prev_y;
int dir = 0int index = 1int total = 0;
void init();
void input();
void Move_Tornado();
void move();
void dust();
bool check_map_range(int& next_x, int& next_y);
int main() {
    init();
    input();
    Move_Tornado();
}
void init() {
    ios::sync_with_stdio(false);
    cin.tie(0);
}
void input() {
    cin >> N;
    for (int i = 1; i <= N; i++) {
        for (int j = 1; j <= N; j++) {
            cin >> A[i][j];
            total += A[i][j];
        }
    }
}
void Move_Tornado() {
    Tornado_x = N / 2 + 1;
    Tornado_y = N / 2 + 1;
    dir = 0;
    index = 1;
    A[Tornado_x][Tornado_y] = 0;
    while (Tornado_x != 1 || Tornado_y != 1) {
        if (index == N - 1) {
            move();
            move();
            move();
        }
        else {
            move();
            move();
            index++;
        }
    }
    int total_temp = 0;
    for (int i = 1; i <= N; i++) {
        for (int j = 1; j <= N; j++) {
            total_temp += A[i][j];
        }
    }
    cout << total - total_temp;
}
void move() {
    for (int i = 0; i < index; i++) {
        prev_x = Tornado_x;
        prev_y = Tornado_y;
        Tornado_x += dx[dir];
        Tornado_y += dy[dir];
        dust();
    }
    dir += 1;
    if (dir == 4)
        dir = 0;
}
void dust() {
    // 0    1      2      3
    // 왼쪽 아래쪽 오른쪽 위쪽
    // x -> y -> a 순으로 먼지 날릴 양 계산
    // dir 방향에서 +1, -1 방향으로 퍼진다
    int dir_dust[2= { dir + 1,dir - 1 };
    int dust_total = A[Tornado_x][Tornado_y];
    int alpah_dust = dust_total;
    A[Tornado_x][Tornado_y] = 0;
    int alpha_x = Tornado_x + dx[dir];
    int alpha_y = Tornado_y + dy[dir];
    if (dir_dust[0== 4)
        dir_dust[0= 0;
    if (dir_dust[1== -1)
        dir_dust[1= 3;
    for (int i = 0; i < 2; i++) {
        int next_x = prev_x + dx[dir_dust[i]];
        int next_y = prev_y + dy[dir_dust[i]];
        if (check_map_range(next_x, next_y) == true) {
            A[next_x][next_y] += dust_total * 0.01;
        }
        alpah_dust -= int(dust_total * 0.01);
    }
    for (int i = 0; i < 2; i++) {
        int next_x = Tornado_x;
        int next_y = Tornado_y;
        for (int j = 0; j < 2; j++) {
            next_x += dx[dir_dust[i]];
            next_y += dy[dir_dust[i]];
            if (check_map_range(next_x, next_y) == true) {
                if (j == 0) {
                    A[next_x][next_y] += dust_total * 0.07;
                    alpah_dust -= int(dust_total * 0.07);
                }
                else if (j == 1) {
                    A[next_x][next_y] += dust_total * 0.02;
                    alpah_dust -= int(dust_total * 0.02);
                }
            }
            else {
                if (j == 0) {
                    alpah_dust -= int(dust_total * 0.07);
                }
                else if (j == 1) {
                    alpah_dust -= int(dust_total * 0.02);
                }
            }
            
        }
    }
    for (int i = 0; i < 2; i++) {
        int next_x = alpha_x + dx[dir_dust[i]];
        int next_y = alpha_y + dy[dir_dust[i]];
        if (check_map_range(next_x, next_y) == true) {
            A[next_x][next_y] += dust_total * 0.1;
        }
        alpah_dust -= int(dust_total * 0.1);
    }
    int next_x = alpha_x + dx[dir];
    int next_y = alpha_y + dy[dir];
    if (check_map_range(next_x, next_y) == true) {
        A[next_x][next_y] += dust_total * 0.05;
    }
    alpah_dust -= int(dust_total * 0.05);
    if (check_map_range(alpha_x, alpha_y) == true) {
        A[alpha_x][alpha_y] += alpah_dust;
    }
}
 
bool check_map_range(int& next_x, int& next_y){
    if (next_x >= 1 && next_x <= N && next_y >= 1 && next_y <= N) {
        return true;
    }
    return false;
}
 
cs

코드를 줄이면 120? 까지도 줄일 수 있을거같지만 귀찮음..

+ Recent posts