-
13913번: 숨바꼭질 4
수빈이는 동생과 숨바꼭질을 하고 있다. 수빈이는 현재 점 N(0 ≤ N ≤ 100,000)에 있고, 동생은 점 K(0 ≤ K ≤ 100,000)에 있다. 수빈이는 걷거나 순간이동을 할 수 있다. 만약, 수빈이의 위치가 X일
www.acmicpc.net
문제
수빈이는 동생과 숨바꼭질을 하고 있다. 수빈이는 현재 점 N(0 ≤ N ≤ 100,000)에 있고, 동생은 점 K(0 ≤ K ≤ 100,000)에 있다. 수빈이는 걷거나 순간이동을 할 수 있다. 만약, 수빈이의 위치가 X일 때 걷는다면 1초 후에 X-1 또는 X+1로 이동하게 된다. 순간이동을 하는 경우에는 1초 후에 2*X의 위치로 이동하게 된다.
수빈이와 동생의 위치가 주어졌을 때, 수빈이가 동생을 찾을 수 있는 가장 빠른 시간이 몇 초 후인지 구하는 프로그램을 작성하시오.
조건
[입력]
첫 번째 줄에 수빈이가 있는 위치 N과 동생이 있는 위치 K가 주어진다. N과 K는 정수이다.
[출력]
첫째 줄에 수빈이가 동생을 찾는 가장 빠른 시간을 출력한다.
둘째 줄에 어떻게 이동해야 하는지 공백으로 구분해 출력한다.
풀이
해당 문제는 bfs를 이용해서 해결했다. 처음에 이동 경로에 대해서는 list를 이용해 담아주면 되겠다고 생각했는데 시간 초과가 발생했고 질문게시판을 보던 중 이동 경로를 부모 배열에 담아서 해결하는 방법이 있다는 것을 알게 되어 해당 방법으로 문제를 해결했다.
큐에 데이터 형식을 class를 하나 두어서 위치와 이동 횟수를 넣는 식으로 진행했고, bfs를 돌리는 과정에서 조건을 통해서 이동 횟수를 저장하고, 큐에 추가해줌과 동시에 부모를 가리키는 배열도 갱신해주는 방식으로 문제를 해결했다. 로직은 아래와 같다.
1. 입력 처리를 하고 bfs를 돌린다.
2. add, sub, mil에 대해서 방문 체크와 범위 체크를 한 뒤 큐에 넣어준다. 이때 가려는 배열에 이전 값을 넣어준다.
3. 위를 계속 반복하다가 K에 도착하면 이동 횟수를 출력한다.
4. 스택을 이용해 역순으로 시작까지의 경로를 저장한다.
5. StringBuilder를 이용해 스택의 값을 하나씩 빼서 저장해준 뒤 최종 출력해준다.
코드
import java.io.BufferedReader; import java.io.InputStreamReader; import java.util.LinkedList; import java.util.Queue; import java.util.Stack; import java.util.StringTokenizer; public class Main { static int N, K, parent[]; static boolean[] visit; static Queue<Node> q = new LinkedList<>(); public static void main(String[] args) throws Exception { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); StringTokenizer st = new StringTokenizer(br.readLine()); N = Integer.parseInt(st.nextToken()); K = Integer.parseInt(st.nextToken()); parent = new int[100001]; // 자신의 부모를 가르키는 배열 visit = new boolean[100001]; // 방문 체크 visit[N] = true; q.offer(new Node(N, 0)); bfs(); } private static void bfs() { while (!q.isEmpty()) { Node n = q.poll(); if (n.index == K) { System.out.println(n.cnt); // 이동 횟수를 출력해줌 Stack<Integer> s = new Stack<>(); // 스택에 먼저 역순으로 타고 시작까지의 경로를 저장 int p = n.index; s.push(p); while (p != N) { p = parent[p]; s.push(p); } StringBuilder sb = new StringBuilder(); while (!s.isEmpty()) { // 스택에서 하나씩 빼내면서 출력값에 추가해줌. sb.append(s.pop()).append(" "); } System.out.println(sb.toString()); return; } int add = n.index + 1; int sub = n.index - 1; int mul = n.index * 2; if (add <= 100000 && !visit[add]) { q.offer(new Node(add, n.cnt + 1)); parent[add] = n.index; visit[add] = true; } if (sub >= 0 && !visit[sub]) { q.offer(new Node(sub, n.cnt + 1)); parent[sub] = n.index; visit[sub] = true; } if (mul <= 100000 && !visit[mul]) { q.offer(new Node(mul, n.cnt + 1)); parent[mul] = n.index; visit[mul] = true; } } } static class Node { int index, cnt; Node(int index, int cnt) { this.index = index; this.cnt = cnt; } } }
GitHub - JUNGSOONIL/Algorithm-JAVA: 알고리즘 문제 해결 자바 소스 코드
알고리즘 문제 해결 자바 소스 코드. Contribute to JUNGSOONIL/Algorithm-JAVA development by creating an account on GitHub.
github.com
참고
해당 문제는 아래의 숨바꼭질 문제와 연관된 문제다.
Baekjoon 1697 숨바꼭질 JAVA
https://www.acmicpc.net/problem/1697 1697번: 숨바꼭질 수빈이는 동생과 숨바꼭질을 하고 있다. 수빈이는 현재 점 N(0 ≤ N ≤ 100,000)에 있고, 동생은 점 K(0 ≤ K ≤ 100,000)에 있다. 수빈이는 걷거나 순..
soonil.tistory.com
Baekjoon 12851 숨바꼭질 2 JAVA
12851번: 숨바꼭질 2 수빈이는 동생과 숨바꼭질을 하고 있다. 수빈이는 현재 점 N(0 ≤ N ≤ 100,000)에 있고, 동생은 점 K(0 ≤ K ≤ 100,000)에 있다. 수빈이는 걷거나 순간이동을 할 수 있다. 만약, 수빈
soonil.tistory.com
Baekjoon 13549 숨바꼭질 3 JAVA
https://www.acmicpc.net/problem/13549 13549번: 숨바꼭질 3 수빈이는 동생과 숨바꼭질을 하고 있다. 수빈이는 현재 점 N(0 ≤ N ≤ 100,000)에 있고, 동생은 점 K(0 ≤ K ≤ 100,000)에 있다. 수빈이는 걷거..
soonil.tistory.com
728x90'알고리즘 > Baekjoon' 카테고리의 다른 글
Baekjoon 4577 소코반 JAVA (0) 2022.06.13 Baekjoon 8972 미친 아두이노 JAVA (0) 2022.06.08 Baekjoon 17086 아기 상어 2 JAVA (0) 2022.06.05 Baekjoon 1302 베스트셀러 JAVA (0) 2022.06.01 Baekjoon 14248 점프 점프 JAVA (0) 2022.05.31 댓글