BOJ 3190 뱀

대학교 동기들이 물어봐서 다시 한 번 풀어봤습니다.

문제에서 요구하는데로 그대로 따라하면 해결할 수 있습니다.

저는 map에서 0은 빈 공간, 1은 뱀을 나타내는 값, 2는 사과를 저장합니다.

turnInfo에는 문제에서 주어지는 L의 값들을 구조체로 저장했습니다.

나머지는 주석을 달아놓았습니다.

궁금한 점은 댓글달아주세요^^

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
#include <iostream>
#include <queue>
 
#define MAX_SIZE 100
#define mp make_pair
 
using namespace std;
 
typedef pair<intint> pii;
typedef struct {
    int sec;
    int dir;
}TurnInfo;
 
 
int n; //보드 크기
int map[MAX_SIZE][MAX_SIZE]; // 사과는 2, 뱀은 1, 맵은 0
TurnInfo turnInfo[MAX_SIZE];
int dx[4= { -1100 };
int dy[4= { 00-11 };
 
//오른쪽 : 위 -> 오, 아래 -> 왼, 오 -> 아, 왼 -> 위
//왼쪽 : 위 -> 왼, 아래 -> 오른, 오 -> 위, 왼 -> 아
 
//r : 0 -> 3, 1 -> 2, 3 -> 1, 2 -> 0
//l : 0 -> 2, 1 -> 3, 3 -> 0, 2 -> 1
 
int turn(int now, int next)
{
    if (next == 0// 왼쪽
    {
        if (now == 0 || now == 1return (now + 2) % 4;
        else return 3 - now;
    }
    else // 오른쪽
    {
        if (now == 0 || now == 1return 3 - now;
        else return (now + 2) % 4;
    }
}
 
bool isDead(pii headPos) {
    //벽을 박았는지
    if (headPos.first < 0 || headPos.second < 0 || headPos.first >= n || headPos.second >= n) {
        return 1;
    }
    //내 몸을 부딪혔는지?
    else if (map[headPos.first][headPos.second] == 1) {
        return 1;
    }
 
    //위에 속하지 않으면 살았다.
    return 0;
}
 
int main() {
    cin >> n;
 
    //사과 개수
    int k;
    cin >> k;
 
    //사과를 2로 맵에 표시
    for (int i = 0; i < k; i++) {
        int x, y;
        cin >> x >> y;
        map[x - 1][y - 1= 2;
    }
 
 
    //방향 변환 개수
    int l;
    cin >> l;
 
    //방향 변환 x는 시간 c는 방향
    for (int i = 0; i < l; i++) {
        int x;
        char c;
        cin >> x >> c;
 
        turnInfo[i].sec = x;
 
        if (c == 'L') {
            turnInfo[i].dir = 0;
        }
        else {
            turnInfo[i].dir = 1;
        }
    }
 
    //위에까지 인풋
    
    queue<pii> snakeTrace; // 뱀 자취
    int sec = 0// 현재 시간은 0
    int snakeDir = 3// 초기 방향 오른쪽
 
    pii headPos;//머리 위치
    headPos.first = headPos.second = 0// 뱀 머리 위치 0, 0으로
 
    //turnInfo 인덱스
    int turnInfoIdx = 0;
 
    //뱀이 죽지않으면 루프
    while (!isDead(headPos)) {
        //현재시간이 0이 아닌데 map이 0이면 꼬리가 잘려야함
        //맵은 0이면 빈공간, 1이면 뱀의 몸, 2이면 사과
        //sec != 0 이 조건은 시작점은 무조건 map이 0이기 때문에 시작하자마자 꼬리가 잘릴 순 없음
        if (sec != 0 && map[headPos.first][headPos.second] == 0) {    
            map[snakeTrace.front().first][snakeTrace.front().second] = 0;//꼬리의 map을 빈공간으로 만들어줌 즉, 잘라버림
            snakeTrace.pop();//내 몸을 보관하고 있는 큐에서 꼬리를 버림
        }
 
        //머리가 위치한 곳의 맵을 1로만들어줌
        map[headPos.first][headPos.second] = 1;
        snakeTrace.push(headPos);//뱀의 머리를 넣기
 
        //turnInfoIdx가 입력받은 l보다 작아야함 같거나 크다면 방향을 전환할 곳이 없으므로 가던곳으로 가야함
        if (turnInfoIdx < l) {
            if (sec == turnInfo[turnInfoIdx].sec) {//현재시간과 방향전환해야하는 시간이 같으면
                snakeDir = turn(snakeDir, turnInfo[turnInfoIdx].dir);//뱀의 방향을 전환해줌
                turnInfoIdx++;//턴정보 인덱스 증가
            }
        }
 
        //뱀의 머리를 다음 위치로 이동시킴
        headPos.first += dx[snakeDir];
        headPos.second += dy[snakeDir];
        sec++;    //시간증가
    }
 
    cout << sec;
 
    return 0;
}
cs


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

[2140] 지뢰찾기  (0) 2017.12.27
[12845] 모두의 마블  (0) 2017.08.26
[12841] 정보대 등산  (0) 2017.08.23
[1700] 멀티탭 스케줄링  (0) 2017.08.01
[1992] 쿼드 트리  (0) 2017.07.30

BOJ 2140 지뢰찾기

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

단순하게 구현하면 되는 문제입니다.

맵의 크기가 n이라고 가정했을 때,

테두리 옆의 # 즉 숫자 옆의 #들만 신경쓰면 됩니다.

그 외의 #들은 지뢰가 있을 수도 있고 없을 수도 있지만, 저희는 다 있다고 가정하고 풀어야합니다.

문제에서 요구하는 것이 최댓값이기 때문입니다.

테두리 옆의 #들은 8방향으로 검사를 해서 만약 주변의 숫자 중에 0인 것이 없다면 지뢰가 있어야하는 자리입니다.

이것만 유의한다면 어렵지 않게 해결할 수 있습니다.

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
#include <iostream>
#include <queue>
 
using namespace std;
 
char map[100][105];
int dx[8= { 10-10-111-1 };
int dy[8= { 010-111-1-1 };
int n;
 
bool check(int x, int y) {
    for (int i = 0; i < 8; i++) {
        int nx = x + dx[i];
        int ny = y + dy[i];
 
        if (nx < 0 || ny < 0 || nx >= n || ny >= n) {
            continue;
        }
 
        if (map[nx][ny] == '0'return 0;
    }
 
    return 1;
}
 
void doMinus(int x, int y) {
    for (int i = 0; i < 8; i++) {
        int nx = x + dx[i];
        int ny = y + dy[i];
 
        if (nx < 0 || ny < 0 || nx >= n || ny >= n) {
            continue;
        }
 
        if (map[nx][ny] >= '0' && map[nx][ny] <= '9') map[nx][ny]--;
    }
}
 
int main() {
    cin >> n;
 
    if (n <= 2) {
        cout << 0;
        return 0;
    }
 
    int ret = (n - 2* (n - 2);
 
    for (int i = 0; i < n; i++cin >> map[i];
 
    for (int i = 1; i < n - 1; i++) {
        for (int j = 1; j < n - 1; j++) {
            if (i == 1 || j == 1 || i == n - 2 || j == n - 2) {
                if (check(i, j)) {
                    doMinus(i, j);
                }
                else {
                    ret--;
                }
            }
        }
    }
 
    cout << ret;
 
    return 0;
}
cs


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

[3190] 뱀  (4) 2018.01.10
[12845] 모두의 마블  (0) 2017.08.26
[12841] 정보대 등산  (0) 2017.08.23
[1700] 멀티탭 스케줄링  (0) 2017.08.01
[1992] 쿼드 트리  (0) 2017.07.30

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


간단한 문제입니다.

레벨이 변하지 않으므로, 최대값의 레벨을 가진 카드의 양방향으로 더해나가면 해결되는 문제입니다.


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 <string>
#include <vector>
#include <queue>
#include <string.h>
#include <cmath>
#define ll long long
#define mp make_pair
#define pii pair<intint>
#define vi vector<int>
#define vii vector<pair<intint> >
#define vll vector<ll>
 
#define MOD 86400
#define INF 0x7fffffff
#define MAX_SIZE (int)1e5
 
using namespace std;
//ios::sync_with_stdio(false); cin.tie(0);
int n;
int arr[(int)1e3];
 
int main() {
    ios::sync_with_stdio(false); cin.tie(0);
    cin >> n;
 
    int M = 0;
    int pos;
 
    for (int i = 0; i < n; i++) {
        cin >> arr[i];
 
        if (arr[i] > M) {
            M = arr[i];
            pos = i;
        }
    }
 
    int ret = 0;
 
    for (int i = pos - 1; i >= 0; i--) {
        ret += M + arr[i];
    }
 
    for (int i = pos + 1; i < n; i++) {
        ret += M + arr[i];
    }
 
    cout << ret;
 
    return 0;
}
cs


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

[3190] 뱀  (4) 2018.01.10
[2140] 지뢰찾기  (0) 2017.12.27
[12841] 정보대 등산  (0) 2017.08.23
[1700] 멀티탭 스케줄링  (0) 2017.08.01
[1992] 쿼드 트리  (0) 2017.07.30

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


단순 구현? 일 것 같습니다.


횡단보도를 한 번만 할 수 있다?


즉. 왼쪽길로 쭉 가다가 횡단보도 한번 건너서 오른쪽 길로 쭉 갈 수 밖에 없습니다.

여기서 두가지 예외는 왼쪽 길로 아예 안가고 횡단 보도를 바로 건너서 오른쪽 길로 쭉 가는 방법과

왼쪽 길로 쭉 가서 횡단 보도를 건너서 정보대에 도착하는 방법이 있는데

사실 예외라고 하기엔.. 예외처리를 안해줘도 되기 때문에....ㅎㅎ...



그림으로 표현하면 이렇습니다!

빨간색길과 검은색길 초록색 길!


다 같은 말이죠


그렇다면 i번째에서 횡단보도를 건너는 거리의 식은


거리i = i번째 까지의 왼쪽 길 연속 합 + 횡단 보도 i의 거리 + 1부터 정보대까지의 오른쪽 거리 - 1부터 i까지의 거리


입니다.!


코드는 아래와 같습니다.


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
#include <iostream>
#include <string>
#include <vector>
#include <queue>
 
#define ll long long
#define mp make_pair
#define pii pair<intint>
#define vi vector<int>
#define vii vector<pair<intint> >
#define vll vector<ll>
 
#define MOD 86400
#define INF 0x7fffffff
#define MAX_SIZE (int)1e5
 
using namespace std;
//ios::sync_with_stdio(false); cin.tie(0);
 
int cross[MAX_SIZE + 1];
ll edge[MAX_SIZE + 1][2];
 
int main() {
    ios::sync_with_stdio(false);
 
    int n;
    cin >> n;
 
    for (int i = 1; i <= n; i++cin >> cross[i];
 
    for (int i = 0; i < 2; i++) {
        for (int j = 2; j <= n; j++) {
            cin >> edge[j][i];
            edge[j][i] += edge[j - 1][i];
        }
    }
 
    ll ret = 1e16;
    int idx = 0;
 
    for (int i = 1; i <= n; i++) {
        ll tmp = edge[i][0+ cross[i] + edge[n][1- edge[i][1];
 
        if (tmp < ret) {
            ret = tmp;
            idx = i;
        }
    }
 
    cout << idx << ' ' << ret;
 
    return 0;
}
 
cs


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

[2140] 지뢰찾기  (0) 2017.12.27
[12845] 모두의 마블  (0) 2017.08.26
[1700] 멀티탭 스케줄링  (0) 2017.08.01
[1992] 쿼드 트리  (0) 2017.07.30
[14488] 준오는 급식충이야!  (0) 2017.07.29

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


운영체제 스케줄링 기법을 이용하면 되는 문제입니다..

(어떤건지는 까먹음..)


분류는 그리디 알고리즘이며,

문제 해결 절차는 이렇습니다.


1. 내가 사용할 아이템(장비???)가 꽂혀있는지 확인합니다.

2. 1에서 꽂혀있으면 다음 장비로 넘어갑니다.

3. 1에서 꽂혀있지 않으면 비어있는 포트가 있는지 확인한다.

4. 3에서 빈 포트가 있으면 그냥 꽂는다.

5. 3에서 빈 포트가 없으면 현재 꽂혀 있는 아이템 중에 나중에 가장 늦게 사용하는 아이템 포트를 뺸다.

6. 1~5를 반복한다.


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
#include <iostream>
#include <algorithm>
#include <stack>
#include <string>
#include <queue>
#include <cstdio>
using namespace std;
 
#define ll long long
#define MOD ((int)1e9 + 9)
#define MAX_SIZE (int)1e5
#define mp make_pair
#define INF 987654321
#define pii pair<intint>
//ios::sync_with_stdio(false); cin.tie(0);
 
int arr[100];
bool use[100];
int tab[100];
 
int main() {
    ios::sync_with_stdio(false); cin.tie(0);
    int n, nn;
    cin >> n >> nn;
 
    for (int i = 0; i < nn; i++) {
        cin >> arr[i];
        arr[i]--;
    }
 
    int ret = 0;
    int tabIdx = 0;
 
    for (int i = 0; i < nn; i++) {
 
        if (use[arr[i]]) continue//사용하던 아이템임        
                                   //멀티탭 공간이 남음
        else if (tabIdx < n) {
            tab[tabIdx++= arr[i];
            use[arr[i]] = 1;
            continue;
        }
 
 
        ret++// 위 두가지 경우를 제외하고는 뽑을 수 밖에 없음.
 
        int port = 0;
        int farDistance = 0;
 
        //멀티탭에 꽂혀있는 것을 검사
        for (int j = 0; j < n; j++) {
            int distance = INF;
 
            for (int k = i + 1; k < nn; k++) {
                if (tab[j] == arr[k]) {
                    distance = k;
                    break;
                }
            }
 
            if (distance > farDistance) {
                port = j;
                farDistance = distance;
            }
        }
 
        //현재 꽂혀있는 것 중에 가장 먼 아이템을 포트에서 제거
        use[tab[port]] = 0;
        use[arr[i]] = 1;
        tab[port] = arr[i];
    }
 
    cout << ret;
 
    return 0;
}
 
cs


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

[12845] 모두의 마블  (0) 2017.08.26
[12841] 정보대 등산  (0) 2017.08.23
[1992] 쿼드 트리  (0) 2017.07.30
[14488] 준오는 급식충이야!  (0) 2017.07.29
[1913] 달팽이  (0) 2017.07.27

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


이 문제는 재귀로 쉽게 해결할 수 있습니다.


문제 해결 순서는


1. 해당 범위의 값이 같은지 확인한다.

2. 1에서 같으면 그 값을 출력한다.

3. 1에서 다르면 '('를 출력하고 재귀를 통해 해당 영역을 4개로 나눈다.

4. 재귀로 들어가서 1 ~ 3까지 순서를 반복한다.

5. 재귀호출이 끝나고 ')'를 출력한다.


풀 코드입니다.

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
#include <iostream>
#include <algorithm>
#include <stack>
#include <string>
using namespace std;
 
#define ll long long
#define MOD ((int)1e9 + 9)
#define MAX_SIZE (int)1e5
#define mp make_pair
#define INF 987654321
#define pii pair<intint>
//ios::sync_with_stdio(false); cin.tie(0);
 
char map[1 << 6][1 << 6 + 1];
 
bool isSame(int x1, int y1, int x2, int y2) {
    char tmp = map[x1][y1];
 
    for (int i = x1; i <= x2; i++) {
        for (int j = y1; j <= y2; j++) {
            if (tmp != map[i][j]) return 0;
        }
    }
 
    return 1;
}
 
void f(int x1, int y1, int x2, int y2) {
 
    if (isSame(x1, y1, x2, y2)) cout << map[x1][y1];
    else {
        cout << '(';
        int midX = (x1 + x2) / 2;
        int midY = (y1 + y2) / 2;
 
        f(x1, y1, midX, midY);
        f(x1, midY + 1, midX, y2);
        f(midX + 1, y1, x2, midY);
        f(midX + 1, midY + 1, x2, y2);
        cout << ')';
    }
}
 
int main() {
    ios::sync_with_stdio(false); cin.tie(0);
 
    int n;
    cin >> n;
 
    for (int i = 0; i < n; i++cin >> map[i];
    
    f(00, n - 1, n - 1);
    
    return 0;
}
cs


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

[12841] 정보대 등산  (0) 2017.08.23
[1700] 멀티탭 스케줄링  (0) 2017.08.01
[14488] 준오는 급식충이야!  (0) 2017.07.29
[1913] 달팽이  (0) 2017.07.27
[14649] 문홍안  (0) 2017.07.27

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


처음에

모든 친구들에 대해서 만족하는 점을 찾으면 되겠다고 생각했습니다.

그래서 이분탐색으로 접근을 했습니다.

하지만 1차원 선상에서 소수(double)에서도 모일 수 있으므로

이분탐색을 사용하기가 애매했습니다.


그래서 다시 생각했는데 

구현하는 것이 정말 단순했습니다.


그냥 N의 시간으로 가면서 모든 학생들이 모일 수 있는 포인트로 좁혀가다가

그 포인트에 벗어나는 학생이 있으면 홍수에 당하는 것이고 아니라면 만날 수 있는 것이라고 생각했습니다.


minPos와 maxPos가 모든 학생들이 접근할 수 있는 범위입니다.


for문안에서 left와 right는 시간 * 속력으로 이동할 수 있는 거리를 구하여 현재 위치에서 더하고 빼서 

움직일 수 있는 범위를 나타냅니다.


첫번째 if문이 있는 경우가 아니라면 모일 수 있는 것입니다.


풀코드입니다.

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
#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
 
#define ll long long
#define MOD ((int)1e9 + 9)
#define MAX_SIZE (int)1e5
#define mp make_pair
#define INF 987654321
#define pii pair<intint>
 
pii v[(int)5e5];
 
int main() {
    ios::sync_with_stdio(false); cin.tie(0);
 
    int n;
    double t;
 
    cin >> n >> t;
 
    for (int i = 0; i < n; i++) {
        cin >> v[i].first ;
    }
 
    for (int i = 0; i < n; i++) {
        cin >> v[i].second;
    }
 
    double minPos = 0, maxPos = INF;
 
    for (int i = 0; i < n; i++) {
        double left = v[i].first - v[i].second * t;
        double right = v[i].first + v[i].second * t;
 
        if (maxPos < left || right < minPos) {
            puts("0");
            return 0;
        }
        
        maxPos = min(maxPos, right);
        minPos = max(minPos, left);
    }
 
    puts("1");
 
    return 0;
}
 
cs


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

[1700] 멀티탭 스케줄링  (0) 2017.08.01
[1992] 쿼드 트리  (0) 2017.07.30
[1913] 달팽이  (0) 2017.07.27
[14649] 문홍안  (0) 2017.07.27
[10986] 나머지 합  (0) 2017.07.24

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


이 문제는 사실 N이 크지 않아서

숫자 1이 있는 곳 부터 차례대로 배열에 숫자를 채워나가도 됩니다.


하지만 저는 y=x와 y=-x의 직선으로 4칸으로 나눠서 문제를 해결했습니다.


toNum()함수를 사용하면 1의 시간으로 해당 위치의 숫자를 찾아낼 수 있습니다.


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
#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
#include <string.h>
using namespace std;
 
#define ll long long
#define MOD (ll)1e15
#define MAX_SIZE (int)1e5
#define mp make_pair
#define INF 987654321
#define pii pair<intint>
//ios::sync_with_stdio(false); cin.tie(0);
int abs(int n) {
    return n >= 0 ? n : -n;
}
 
int toNum(int i, int j) {
    if (abs(i) <= j) return 4 * j * j - j + i + 1;
    else if (abs(i) <= -j) return 4 * j * j - 3 * j - i + 1;
    else if (abs(j) <= -i) return 4 * i * i + 3 * i + j + 1;
    else return 4 * i * i + i - j + 1;
}
 
int main() {
    ios::sync_with_stdio(false); cin.tie(0);
 
    int n;
    cin >> n;
 
    n /= 2;
 
    int k;
    cin >> k;
 
    pii pos;
 
    for (int i = -n; i <= n; i++) {
        for (int j = -n; j <= n; j++) {
            //toNum함수를 이용하여 1의 시간으로 해당 좌표의 숫자를 알아낼 수 있음.
            int ret = toNum(i, j);
            cout << ret << ' ';
 
            //입력받은 k와 같으면 pos변수에 저장
            if (ret == k) {
                pos.first = i, pos.second = j;
            }
        }
        cout << '\n';
    }
 
    cout << pos.first + n + 1 << ' ' << pos.second + n + 1;
 
    return 0;
}
cs


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

[1992] 쿼드 트리  (0) 2017.07.30
[14488] 준오는 급식충이야!  (0) 2017.07.29
[14649] 문홍안  (0) 2017.07.27
[10986] 나머지 합  (0) 2017.07.24
[3474] 교수가 된 현우  (0) 2017.07.13

+ Recent posts