본문 바로가기
Baekjoon/[5] DFS & BFS

[백준] 1697번 숨바꼭질 JAVA (자바) 풀이

by Poorm 푸름 2024. 6. 20.

문제 1697(BFS)

 

 :  수빈이는 현재 점 N(0 ≤ N ≤ 100,000)에 있고, 동생은 점 K(0 ≤ K ≤ 100,000)에 있다

 

 :  수빈이는 걷거나 순간이동을 할 수 있다

    현위치가 X일 때

    걷기 = 1초 후에 X-1 or X+1

    순간이동 = 1초 후에 2*X

 

 :  동생을 찾을 수 있는 가장 빠른 시간이 몇 초 후인지 구하는 프로그램

 

 

[입력]


 :  첫 번째 줄에 수빈이가 있는 위치 N과 동생이 있는 위치 K


 

 [출력]


 :  동생을 찾는 가장 빠른 시간을 출력

 

 

 

 [문제접근]

 

1. 출력 배열 사용하지 말고 큐에다 넣어버리기

  • count[] 배열보다 큐 자체에 넣는 것이 더 간단하다 q.add(new int{start,0}) 추천

 

2. for문 상하좌우 이동을 떠올릴 것

  • 보통 상하좌우 해서 내가 갈 수 있는 방향만큼 for문을 돌려 다음 위치를 큐에 넣어준다
  • 지금은 갈 수 있는 위치가 3가지이다
    • 첫번째 X - 1
    • 두번째 X + 1
    • 세번째 X * 2

 

3. visit 크기와 next 범위

  • arr배열이 있어서 위치들의 범위가 명확한 것이 아니다
    가령 K가 17이라고 하더라도 수빈이가 18을 거쳐서 17로 갈 수 있기 때문에 
    대략 visit 크기는 K의 최대 입력인 100000만큼만 담아줬다
  • next 범위도 마찬가지 100000까지 해줬는데 안돌아갈 경우 범위를 좀 더 크게 잡아야한다

 

4. bfs를 for문이나 재귀에 사용하지 말 것

  • for(){ bfs } 하지말 것 (bfs 메서드 내에서 큐에 계속 추가하면서 반복하면 된다)
  • bfs메서드 내에서 다시 bfs를 호출하지 말 것 (백트래킹이나 dfs와는 다르다)

       

 

 [코드]

import java.io.*;
import java.util.*;
public class Main{
    static int N,K;
    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());
        visit=new boolean[100001];
        
        bfs(N);
    }
    
    static void bfs(int start){
        Queue<int[]> q = new LinkedList<>();
        q.add(new int[] {start,0});
        visit[start]=true;
        
        while(!q.isEmpty()){
            int p[] = q.poll();
            if(p[0]==K){
                System.out.println(p[1]);
                return;
            }
            for(int i=0;i<3;i++){
                int next;
                if(i==0)
                    next = p[0]-1;
                else if(i==1)
                    next = p[0]+1;
                else
                    next = p[0]*2;
                
                if(0<=next && next<=100000 &&!visit[next]){
                    q.add(new int[] {next,p[1]+1});
                    visit[next]=true;
                }
            }
        }
    }
}

 

 [해설]
     

 :  static int N,K;
    static boolean visit[];

 

 :  BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    StringTokenizer st = new StringTokenizer(br.readLine());
    N=Integer.parseInt(st.nextToken());  수빈 위치
    K=Integer.parseInt(st.nextToken());  동생 위치
    visit=new boolean[100001];  방문기록 체크
        
 :  bfs(N);  bfs 실행
    
    
 :  static void bfs(int start){  
        Queue<int[]> q = new LinkedList<>();  큐 선언
        q.add(new int[] {start,0});  큐 추가
        visit[start]=true;  방문처리
        
        while(!q.isEmpty()){
            int p[] = q.poll();  큐에서 뽑기
            if(p[0]==K){  현위치 K일 경우 종료
                System.out.println(p[1]);  카운트 출력
                return;
            }
            for(int i=0;i<3;i++){  3가지 위치로 이동가능
                int next;
                if(i==0)
                    next = p[0]-1;
                else if(i==1)
                    next = p[0]+1;
                else
                    next = p[0]*2;
                
                if(0<=next && next<=100000 &&!visit[next]){  갈 수 있는 위치라면
                    q.add(new int[] {next,p[1]+1});  큐에 추가
                    visit[next]=true;  방문처리
                }
            }
        }
   }



 

 

이제 풀어보러 갈께요 :)



 

* 독학으로 익히는 코딩이라 틀린 것이 있을 수 있습니다. 오류가 있다면 댓글을 통해 알려주세요. 감사합니다. *