일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- boj 1464
- 그래프 이론
- 이분 탐색
- 백준 1464
- 재귀
- 그래프탐색
- 그래프 탐색
- 비트마스킹
- Lis
- 2493 백준
- 결정문제
- 패스트캠퍼스
- parametric search
- 깊이 우선 탐색
- 분할정복
- 이분탐색
- 결정 문제
- 백준 뒤집기 3
- 구현
- 브루트포스
- DP
- 서로소 집합
- 1939백준
- 뒤집기 3
- 최장증가수열
- union find
- disjoint set
- 최장길이바이토닉수열
- bfs
- 그래프이론
- Today
- Total
알고리즘 문제풀이
[BOJ] 13549번 - 숨바꼭질 3 본문
백준 13549번 - 숨바꼭질 3
시간제한 | 메모리 제한 | 제출 | 정답 | 맞은 사람 | 정답 비율 |
---|---|---|---|---|---|
2 초 | 512 MB | 19622 | 5890 | 3680 | 26.760% |
문제
수빈이는 동생과 숨바꼭질을 하고 있다. 수빈이는 현재 점 N(0 ≤ N ≤ 100,000)에 있고, 동생은 점 K(0 ≤ K ≤ 100,000)에 있다. 수빈이는 걷거나 순간이동을 할 수 있다. 만약, 수빈이의 위치가 X일 때 걷는다면 1초 후에 X-1 또는 X+1로 이동하게 된다. 순간이동을 하는 경우에는 0초 후에 2*X의 위치로 이동하게 된다.
수빈이와 동생의 위치가 주어졌을 때, 수빈이가 동생을 찾을 수 있는 가장 빠른 시간이 몇 초 후인지 구하는 프로그램을 작성하시오.
입력
첫 번째 줄에 수빈이가 있는 위치 N과 동생이 있는 위치 K가 주어진다. N과 K는 정수이다.
출력
수빈이가 동생을 찾는 가장 빠른 시간을 출력한다.
예제 입력 1
5 17
예제 출력 1
2
출처
www.acmicpc.net/problem/13549
13549번: 숨바꼭질 3
수빈이는 동생과 숨바꼭질을 하고 있다. 수빈이는 현재 점 N(0 ≤ N ≤ 100,000)에 있고, 동생은 점 K(0 ≤ K ≤ 100,000)에 있다. 수빈이는 걷거나 순간이동을 할 수 있다. 만약, 수빈이의 위치가 X일
www.acmicpc.net
알고리즘 분류
- 그래프 이론
- 자료 구조
- 그래프 탐색
- 너비 우선 탐색
- 다익스트라
- 0-1 너비 우선 탐색
접근 방법
현재 수빈이가 위치한 곳을 X라고 가정해보자.
먼저 수빈이가 현재 위치 X까지 올 때까지 걸린 시간과 동일한 시간이 걸리는 좌표는 X, 2X, 4X, 8X, ...
( until kX <= 100,000 , k는 상수)가 될 것이다.
그러면 ( X ~ 2X 사이의 있는 좌표로 가기 위한 최소 시간 ), ( 2X ~ 4X 사이의 있는 좌표로 가기 위한 최소 시간 ), ... 은 어떻게 구할 것인가?
특정 위치 K부터 시작하여 K+1, K-1, 2*K를 그래프의 정점으로 보고 해당 위치로 가기 위한 추가 시간을 간선으로 본다면 위 문제는 수빈이가 출발한 위치 N 으로 부터 특정 위치 K까지의 최단 경로가 된다.
따라서, 그래프의 특정 정점에서 ~ 도착 위치까지의 최단 경로를 구하는 탐색 알고리즘을 쓰면 되겠다.
필자는 다익스트라 알고리즘을 활용하여 구현하였다.
다익스트라 알고리즘을 Priority Queue를 이용하면, O(|E|log|V|)으로 해결 할 수 있는데 필자가 아래에 구현한 코드에서 탐색 횟수는 최대 (2-1) + (4-2) + (8-4) + (16 - 8) + .... + (65536 - 32768) = ${2^{16} - 1}$ 번을 넘지않는다( X가 1일 때가 최악의 경우 ). 즉 다익스트라 알고리즘으로 충분히 풀 수 있다.
로직은 다음과 같다.
먼저 { 현재 위치까지 오는데 걸린 시간, 현재 위치 } 쌍을 우선순위 큐에 넣어준다.
만약, 현재 위치까지 오는데 걸린 시간이 이전에 구했던 최소 시간보다 더 작다면 이 경로로 탐색을 진행하는 것이 의미가 없으므로 탐색을 중단한다. 해당 작업을 반복한다면 수빈이가 출발한 위치(N)부터 특정 지점(K)까지의 최단경로를 알 수 있게 된다.
소스 코드
#include <bits/stdc++.h>
using namespace std;
int N, K;
int main(void){
ios_base::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cin >> N >> K ;
int dist[200001];
for(auto& it : dist) it = 1e9;
dist[N] = 0;
// { 현재 위치 까지 오는데 걸린 시간, 현재 위치 }
priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> PQ;
PQ.push({0, N});
while(!PQ.empty()){
auto top = PQ.top(); PQ.pop();
int cost = top.first, pos = top.second;
if( cost > dist[pos] ) continue;
int nPos = pos + 1;
if( 0 <= nPos && nPos <= 200000 && dist[nPos] > dist[pos] + 1 ){
dist[nPos] = dist[pos] + 1;
PQ.push({cost+1, nPos});
}
nPos = pos - 1;
if( 0 <= nPos && nPos <= 200000 && dist[nPos] > dist[pos] + 1 ){
dist[nPos] = dist[pos] + 1;
PQ.push({cost+1, nPos});
}
nPos = pos * 2;
if( 0 <= nPos && nPos <= 200000 && dist[nPos] > dist[pos] ){
dist[nPos] = dist[pos] ;
PQ.push({cost, nPos});
}
}
cout << dist[K] ;
return 0;
}
'자료구조 + 알고리즘 > [BOJ]' 카테고리의 다른 글
[BOJ] 14002번 - 가장 긴 증가하는 부분 수열 4 (0) | 2021.02.20 |
---|---|
[BOJ] 11049번 - 행렬 곱셈 순서 (0) | 2021.02.19 |
[BOJ] 1082번 - 방 번호 (0) | 2021.02.10 |
[BOJ] 2166 번 - 다각형의 면적 (0) | 2021.02.06 |
[BOJ] 1495번 - 기타리스트 (0) | 2021.02.03 |