채굴
문제 해석
- NxM 크기의 광산이 있을 때, 채굴기가 원하는 광물의 수 K이상을 채굴할 수 있는 최소의 D를 구하는 문제입니다.
- 채굴기는 공기와 맞닿아 있는 광물 하나를 골라 채굴할 수 있습니다.
- 채굴기의 성능 D에 대해, 강도가 D이하인 광물들만 채굴할 수 있습니다.
설계(5)
- 정해놓은 D가 있을 때, 채굴기가 채굴할 수 있는 수를 탐색하기 위해서는 O(NM)의 시간복잡도가 필요합니다.
- D를 정하는데 범위가 1<= D <= 10^6 이므로, 완전탐색을 하면 시간초과가 될 것입니다.
- D를 정하는데 이분탐색을 이용하여 O(logD)로 최적화시킬 수 있으며, 최종적으로 O(NMlogD)로 시간안에 해결이 가능합니다.
- bfs탐색을 이용하여 채굴할 수 있는 수를 카운트해서 이분탐색을 통해 최소값을 갱신시킵니다.
구현(30)
코드
#include <iostream>
#include <queue>
#include <cstring>
using namespace std;
#define MAXN 1000
int N,M,K;
int map[MAXN][MAXN];
bool visited[MAXN][MAXN];
int dx[] = {0,0,1,-1};
int dy[] = {1,-1,0,0};
bool possible(int limits){
memset(visited,false,sizeof(visited));
queue<pair<int,int> > q;
int sum = 0;
for (int i = 0 ; i < N; i++){
if (!i){
for (int j = 0 ;j < M; j++){
if (map[i][j] <= limits){
visited[i][j] = true;
q.push({i,j});
sum++;
}
}
}
else{
if (!visited[i][0] && map[i][0] <= limits){
visited[i][0] = true;
q.push({i,0});
sum++;
}
if (!visited[i][M-1] && map[i][M-1]<=limits){
visited[i][M-1] = true;
q.push({i,M-1});
sum++;
}
}
}
while (!q.empty()){
int x = q.front().first;
int y = q.front().second;
q.pop();
for (int k = 0 ;k< 4; k++){
int nx = x + dx[k];
int ny = y + dy[k];
if (nx < 0 || ny < 0 || nx>=N || ny>=M) continue;
if (visited[nx][ny] || map[nx][ny]>limits) continue;
visited[nx][ny] = true;
q.push({nx,ny});
sum++;
}
}
return (sum>=K);
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cin >> N >> M >> K;
for (int i = 0;i <N; i++){
for (int j = 0 ;j<M;j++){
cin >> map[i][j];
}
}
int low = 1;
int high = 1e6;
int ans = 1e6;
while (low <= high){
int mid = (low + high) / 2;
if (possible(mid)){
high = mid -1;
ans = mid;
}
else{
low = mid + 1;
}
}
cout << ans <<"\n";
return 0;
}
디버깅
- “채굴기가 공기가 맞닿아 있는 광물 하나를 골라 채굴할 수 있다”라는 지문에 대해 의문점이 생긴게, 처음에 이해할 때 하나를 골라서 해당 채굴기가 채굴할 수 있는 광물의 개수를 카운트하는 것으로 이해를 하였습니다.
- 위와 같이 구현했을 시, WA가 나왔습니다.
- 알고보니 “가능한 모든 지점에서 채굴을 시작했을 때, 채굴할 수 있는 개수”가 정확한 요점이었습니다.
- 조건에 맞는 모든 지점을 큐에 추가한 후, bfs를 탐색하도록 하여 맞는 결과를 도출할 수 있었습니다.
제출결과
- 684ms
마무리
- 이분탐색 + bfs 알고리즘을 이용하여 해결할 수 있는 문제였습니다. 지문에 혼동이 있어 디버깅에 시간이 걸렸습니다.