티어 : Sliver 2
정답여부 : 오답
알고리즘 유형 : 그래프 이론, 그래프 탐색, 너비 우선 탐색
시간 제한 : 2초
💡문제
수빈이는 동생과 숨바꼭질을 하고 있다. 수빈이는 현재 점 N(0 ≤ N ≤ 100,000)에 있고, 동생은 점 K(0 ≤ K ≤ 100,000)에 있다. 수빈이는 걷거나 순간이동을 할 수 있다. 만약, 수빈이의 위치가 X일 때 걷는다면 1초 후에 X-1 또는 X+1로 이동하게 된다. 순간이동을 하는 경우에는 1초 후에 2*X의 위치로 이동하게 된다.
수빈이와 동생의 위치가 주어졌을 때, 수빈이가 동생을 찾을 수 있는 가장 빠른 시간이 몇 초 후인지 구하는 프로그램을 작성하시오.
💡입력
첫 번째 줄에 수빈이가 있는 위치 N과 동생이 있는 위치 K가 주어진다. N과 K는 정수이다.
💡출력
수빈이가 동생을 찾는 가장 빠른 시간을 출력한다.
💡예제 입력1
5 17
💡예제 출력1
4
💡문제 분석 요약
- 수빈이는 뒤로 앞으로 순간(?)이동을 통해 동생이 있는 위치까지 빠른시간안에 갈수 있는 최소 시간을 구하면 되는 문제
💡알고리즘 설계
- 해당 문제는 인근으로 구현을 하는 문제로 BFS 문제인걸 눈치를 챘다. (근데 BFS를 알면 뭐함 구현을 못하는데..😢)
- N : 수빈이 위치
- K = 동생 위치
- location : 현 수빈이 위치
- back : 뒤로 이동 -1
- front : 앞으로 이동 +1
- tele : 순간이동 *2
- 수빈이 위치로 큐에 값을 넣어주며 방문을 표시
- location에 현재 수빈이의 위치를 넣어준다
- 현재 location에 -1 , 1 , *2 씩 이동한 거리를 back , front , tele 에 값을 넣어준다.
- 만약 back , front, tele 값들이 0보다 크고 100,000 작으면 que에 추가
- 방문했다고 표시
- 현재 위치에 새로운 위치까지 도달한 시간 +1초를 저장
- 동생이 있는곳 까지 걸린 최소 시간을 출력
💡시간복잡도
- O(N)
💡코드
import java.util.*;
import java.io.*;
public class Main{
static int N, K;
static int arr[];
static boolean visit[];
static int time;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
K = Integer.parseInt(st.nextToken());
arr = new int [100001];
visit = new boolean[100001];
bfs(N);
System.out.println(time);
}
public static void bfs(int start) {
Queue<Integer> que = new LinkedList<>();
int next_x;
que.offer(start);
visit[start] = true;
while(!que.isEmpty()) {
int location = que.poll();
if(location == K) {
return;
}
int back = location - 1;
int front = location + 1;
int tele = location * 2;
if (back >=0 && back <= 100000 && !visit[back]) {
que.offer(back);
visit[back] = true;
time++;
}
if (front >=0 && front <= 100000 && !visit[front]) {
que.offer(front);
visit[front] = true;
time++;
}
if (tele >=0 && tele <= 100000 && !visit[tele]) {
que.offer(tele);
visit[tele] = true;
time++;
}
}
}
}
💡 틀린 이유
고냥 이동할때마다 time++ 해서 출력하면 되는거 아니야? 낄낄 하고 했다가 38초가 나오는 기적을 보았다. ㅋ 항상 잘 하다가도 결국 마지막에 이렇게 큰 실수를 한다. 생각을 해보다 큐 요소를 꺼낼때마다 time이 증가한다. 즉 수빈이가 arr 배열에 각 위치에 도달하기까지 걸린 시간을 저장해야 한다. 위치에 처음 도달했을 때, 그 위치에 도달하기까지 걸린 시간을 arr에 저장하고, 이 시간을 이용하여 다음 위치에 도달하는 데 필요한 시간을 계산해야 하면 된다..
💡 틀린 부분 수정 or 다른 풀이
import java.util.*;
import java.io.*;
public class Main{
static int N, K;
static int arr[];
static boolean visit[];
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
K = Integer.parseInt(st.nextToken());
arr = new int [100001];
visit = new boolean[100001];
bfs(N);
System.out.println(arr[K]);
}
public static void bfs(int start) {
Queue<Integer> que = new LinkedList<>();
int next_x;
que.offer(start);
visit[start] = true;
while(!que.isEmpty()) {
int location = que.poll();
if(location == K) {
return;
}
int back = location - 1;
int front = location + 1;
int tele = location * 2;
if (back >=0 && back <= 100000 && !visit[back]) {
que.offer(back);
visit[back] = true;
arr[back] = arr[location] + 1;
}
if (front >=0 && front <= 100000 && !visit[front]) {
que.offer(front);
visit[front] = true;
arr[front] = arr[location] + 1;
}
if (tele >=0 && tele <= 100000 && !visit[tele]) {
que.offer(tele);
visit[tele] = true;
arr[tele] = arr[location] + 1;
}
}
}
}
💡 느낀점 or 기억할정보
BFS, DFS 구분방법
- BFS : 구현 방법으로 일단 최단 거리를 찾는 경우
- DFS : 모든 노드를 다 방문해야 할 경우
항상 잘 구현했다가 문제에 포인트를 못 보고 틀린 경우가 많은거 같다 ㅜㅜ 생각보다 푸는데 오래 걸리고 구현도 힘들었다. 문뜩 든 생각이지만 이 문제를 DFS로는 어떻게 풀어야 할지는 감이 안 온다…
'CodingTest > Baekjoon' 카테고리의 다른 글
[B0J]전쟁 - 전투(1303번) (0) | 2024.06.19 |
---|---|
[B0J]미로탐색(2178번) (0) | 2024.06.19 |
[B0J]연결 요소의 개수(11724번) (0) | 2024.06.19 |
[B0J]유기농 배추(1012번) (0) | 2024.06.19 |
[B0J]단지번호붙이기(2667번) (0) | 2024.06.19 |