코딩테스트 사이트 : 백준
난이도 : 실버1
풀이 날짜 : 2022.06.18
사용한 풀이 방법 : DFS, BFS
https://www.acmicpc.net/problem/1697
수빈이가 동생위치까지 이동하는
최단 이동횟수
를 구하는 문제이다.
- 일단 수빈이가 이동할 수 있는 방법은 3가지이다.
- 그리고 또 이동할 수 있는 방법은 또 다시 3가지이다.
- DFS로 예상 시간 복잡도 3^n 이 나올것 같지만,
- 우선순위를 잘 두면서 하면 가능할거 같아 보인다.
x-1
=> 시간 복잡도 N 이다.2x
, x+1
=> 시간 복잡도 2^N이다.x-1
을 4번
해야되는데,2x
가 있었을 경우 앞에서 x-1
을 2번
만 해줘도 된다.2x
를 한 횟수를 별도로 세고, 횟수에 맞춰..수빈이 위치 - 동생의 위치
= 나온 값(diff
)을 2^n
으로 나눈 몫 만큼 더한다.수빈 > 동생
) 함수로 구현해준다.public class HideAndSeek {
static int minValue = Integer.MAX_VALUE;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int N = Integer.parseInt(st.nextToken()); //수빈 위치
int K = Integer.parseInt(st.nextToken()); //동생 위치
int count = 0;
int multiTwoCount = 0;
DFS(K,N,0,0);
System.out.println(minValue);
br.close();
}
public static void DFS(int K, int curLocation, int count, int multiTwoCount) {
if(count > minValue){ // 시간초과가 떠서 추가한 코드, 쓸데없는 계산 버림
return;
}
if (curLocation >= K) {
int addCount = moveCalculate(multiTwoCount, curLocation - K);
count += addCount;
if (minValue > count) {
minValue = count;
}
return;
}
//if (curLocation < K)
DFS(K, curLocation * 2, count + 1, multiTwoCount + 1);
DFS(K, curLocation + 1, count + 1, multiTwoCount);
}
public static int moveCalculate(int multiTwoCount, int diff) {
int div = (int) Math.pow(2, multiTwoCount);
int move = 0;
while (diff > 1) {
if ((diff / div) > 0) move += (diff / div);
diff = diff % div;
div /= 2;
}
if (diff == 1) move++;
return move;
}
}
하지만 그 결과는 아래와 같다.
DFS로는 메모리 초과가 나온다.
Depth
를 반환하면,Depth
의 값을 유지하는 것과 방문했는지 유무를 파악하는 것!public class HideAndSeek {
static int K ;
static int N ;
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()); //동생 위치
Queue<Depth> locationQue = new LinkedList<>();
Set<Integer> visited = new HashSet<>();
Depth depth= new Depth(N, 0);
locationQue.add(depth);
int curLocation ;
int curDepth = 0;
while (!locationQue.isEmpty()){
curLocation = locationQue.peek().getLocation();
curDepth = locationQue.peek().getDepth();
locationQue.poll();
//방문했던 곳 다시 가기 방지
if(visited.contains(curLocation)){continue;}
visited.add(curLocation);
// 탈출 조건
if(curLocation == K){
break;
}
// 3가지 경우 적용하기
locationQue.add(new Depth(curLocation - 1,curDepth + 1));
locationQue.add(new Depth(curLocation + 1,curDepth+1));
locationQue.add(new Depth(curLocation * 2,curDepth+1));
}
System.out.println(curDepth);
br.close();
}
}
class Depth{
private int location;
private int depth;
public Depth(int location, int depth) {
this.location = location;
this.depth = depth;
}
public int getLocation() {
return location;
}
public int getDepth() {
return depth;
}
}
visited[]
를 int[]
로 만들어, 요소의 값을 depth
을 넣어준다.package Beakjoon;
import java.io.*;
import java.util.*;
// BFS
public class HideAndSeek {
static int K ;
static int N ;
static int[] visited = new int[100001];
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()); //동생 위치
Queue<Integer> locationQue = new LinkedList<>();
locationQue.add(N);
visited[N] = 1;
int curLocation ;
while (!locationQue.isEmpty()){
curLocation = locationQue.poll();
// 목표 도달
if(curLocation == K){
System.out.println(visited[K] -1 );
break;
}
//방문했던 곳인지 파악하면서 3가지 경우 적용하기
if((curLocation-1) >= 0 && visited[curLocation- 1] == 0 ) {
locationQue.add(curLocation - 1);
visited[curLocation - 1] = visited[curLocation] + 1;
}
if((curLocation +1) < 100001 && visited[curLocation + 1] == 0 ) {
locationQue.add(curLocation + 1);
visited[curLocation + 1] = visited[curLocation] + 1;
}
if((curLocation * 2) < 100001 && visited[curLocation * 2 ] == 0) {
locationQue.add(curLocation * 2);
visited[curLocation * 2] = visited[curLocation] + 1;
}
}
br.close();
}
}
주어진 값이 다음과 같을 때 테스트를 해보자
0 0
0 100000
100000 0