반응형
Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- 퇴사통보
- dfs
- 이분탐색
- incr
- 매개변수탐색
- 성적평가
- 경력
- OFFSET
- boj #19237 #어른 상어
- msSQL
- 소프티어
- BFS
- 13908
- 연결요소
- 물채우기
- Docker
- 기술면접
- upper_bound
- softeer
- 6987
- 백준
- Kafka
- 백트래킹
- @P0
- compose
- 파라메트릭
- BOJ
- 오퍼레터
- 처우산정
- 처우협의
Archives
- Today
- Total
기술 블로그
3197번 백조의 호수 본문
728x90
반응형
https://www.acmicpc.net/problem/3197
# 시간 초과 # 복습 # bfs # 이분 탐색 # 생각 # 아이디어 # queue # 팁 tip
깨달은 점 : 행과 열이 100 이상이면 퍼져나가는 시점을 기록하는 방법을 써보자.
얼음을 한 번 녹일 때마다, bfs로 탐색해서 검사하는 것은 시간 초과가 발생한다.
그래서 시간을 줄이려면 queue를 여러 개 사용해서 구현하거나 약간의 아이디어가 필요하다.
우선 내 코드에서의 핵심은 Map[행][열] 배열이다.
1. 우선 'L'이나 '.'를 melt_queue에 push하여, 최대로 얼음을 녹이는 시점을 구한다.(모든 얼음이 다 녹는 시점)
2. 위에서 최대 시점을 구할 때, Map[행][열] 배열에 각 위치에 맞는 얼음이 녹이는 시점을 기록한다.(87번 째 줄 코드)
3. 1에서 구한 최대 시점을 기준으로 이분 탐색을 실행한다.
4. mid가 Map[y][x]보다 작다는 것은 시점이 mid일 때, Map[y][x]가 아직 녹지 않은 얼음이다.
위의 방법 말고 queue를 여러 개 사용하는 방법이 있다.
1. 우선 한 백조에서 다른 백조로 가는 bfs를 실행하면서, 인접하게 만나는 'X'(얼음)를 큐1에 담는다.
이 큐1은 후에 다시 1에서 활용할 것이다.
2. 그 다음 얼음을 녹인다.
1, 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 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 | #include <bits/stdc++.h> using namespace std; #define Max 1502 int R, C; int dy[4] = { 0, 1, 0, -1 }; int dx[4] = { 1, 0, -1, 0 }; int Map[Max][Max]; bool visit[Max][Max]; char m[Max][Max]; queue<pair<int, int> > melt_queue; pair<int, int> L[2]; // 백조끼리 만날 수 있는지 검사(BFS) bool chk(int Limit) { memset(visit, false, sizeof(visit)); queue<pair<int, int> > q; q.push({ L[0].first, L[0].second }); visit[L[0].first][L[0].second] = true; while (!q.empty()) { int qs = q.size(); while (qs--) { int r = q.front().first; int c = q.front().second; q.pop(); if (r == L[1].first && c == L[1].second) { return true; } for (int i = 0; i < 4; i++) { int y = r + dy[i]; int x = c + dx[i]; // Map[y][x]가 Limit보다 크다는 것은 Limit 시점에서 Map[y][x]는 'X'라는 의미임. if (y < 0 || y >= R || x < 0 || x >= C || visit[y][x] || Map[y][x] > Limit) { continue; } visit[y][x] = true; q.push({ y, x }); } } } return false; } // 얼음이 다 녹는 시점 및 Map[행][열]에 각 얼음이 녹는 시점을 기록 int max_melt() { int ret = 0; while (!melt_queue.empty()) { int mqs = melt_queue.size(); while (mqs--) { int r = melt_queue.front().first; int c = melt_queue.front().second; melt_queue.pop(); for (int i = 0; i < 4; i++) { int y = r + dy[i]; int x = c + dx[i]; if (y < 0 || y >= R || x < 0 || x >= C || visit[y][x]) { continue; } // m[y][x]가 무엇인지 상관없다. // 이유는 어차피 입력할 때 '.'과 'L'만 melt.queue에 push 하였기 때문에 // 점점 퍼져 나가서 ret + 1을 기록한다는 것으로만 이해하면 된다. // X가 있다면 그 부분으로 자동으로 퍼질 것이다. visit[y][x] = true; Map[y][x] = ret + 1; melt_queue.push({ y, x }); } } ++ret; } return ret; } // 이분 탐색 int bt(int Start, int End) { int Left = Start, Right = End, ret = INT32_MAX; // '<' 아니다. while (Left <= Right) { int mid = (Left + Right) / 2; // 최솟값을 찾는다. if (chk(mid)) { ret = min(ret, mid); Right = mid - 1; } else { Left = mid + 1; } } return ret; } int main() { cin.tie(0); cin >> R >> C; int idx = 0; for (int i = 0; i < R; i++) { for (int j = 0; j < C; j++) { cin >> m[i][j]; if (m[i][j] == 'L') { L[idx++] = { i, j }; } if (m[i][j] == 'L' || m[i][j] == '.') { visit[i][j] = true; melt_queue.push({ i, j }); } } } int Limit = max_melt(); printf("%d\n", bt(0, Limit)); return 0; } | cs |
728x90
반응형
'알고리즘 문제 > BOJ' 카테고리의 다른 글
15922번 아우으 우아으이야!! (0) | 2020.03.01 |
---|---|
16925번 문자열 추측 (0) | 2020.02.29 |
16957번 체스판 위의 공 (0) | 2020.02.28 |
18511번 큰 수 구성하기 (0) | 2020.02.28 |
16958번 텔레포트 (0) | 2020.02.27 |