백준 12851 숨바꼭질2 (Java,자바)
오늘 풀어본 문제는
백준 12851번 숨바꼭질 2 입니다.
📕 문제 링크
❗️코드
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
class Subin
{
int x,cnt;
public Subin(int x, int cnt)
{
this.x = x;
this.cnt = cnt;
}
}
public class Main {
static int [] map;
static int [] move = {-1,1,2};
static int [] isVis;
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());
if(n > k)
{
System.out.printf("%d\n%d",n-k,1);
return;
}
map = new int[100001];
isVis = new int[100001];
Arrays.fill(isVis,Integer.MAX_VALUE);
Queue<Subin> q = new LinkedList<>();
q.add(new Subin(n,0));
int minCnt = Integer.MAX_VALUE;
int cnt = 0;
while(!q.isEmpty())
{
Subin cur = q.poll();
if(isVis[cur.x] > cur.cnt) isVis[cur.x] = cur.cnt;
if(cur.cnt > minCnt) break;
if(cur.x == k)
{
minCnt = cur.cnt;
cnt++;
}
for(int i = 0; i < 3; ++i)
{
int m;
if(i == 2) m = cur.x * move[i];
else m = cur.x + move[i];
if(!isValid(m) || cur.cnt >= isVis[m]) continue;
q.add(new Subin(m,cur.cnt+1));
}
}
System.out.printf("%d\n%d",minCnt,cnt);
}
static boolean isValid(int x)
{
return x >= 0 && x < 100001;
}
}
📝 풀이
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
class Subin
{
int x,cnt;
public Subin(int x, int cnt)
{
this.x = x;
this.cnt = cnt;
}
}
public class Main {
static int [] map;
static int [] move = {-1,1,2};
static int [] isVis;
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());
if(n > k)
{
System.out.printf("%d\n%d",n-k,1);
return;
}
map = new int[100001];
isVis = new int[100001];
Arrays.fill(isVis,Integer.MAX_VALUE);
Queue<Subin> q = new LinkedList<>();
q.add(new Subin(n,0));
int minCnt = Integer.MAX_VALUE;
int cnt = 0;
while(!q.isEmpty())
{
Subin cur = q.poll();
if(isVis[cur.x] > cur.cnt) isVis[cur.x] = cur.cnt;
if(cur.cnt > minCnt) break;
if(cur.x == k)
{
minCnt = cur.cnt;
cnt++;
}
for(int i = 0; i < 3; ++i)
{
int m;
if(i == 2) m = cur.x * move[i];
else m = cur.x + move[i];
if(!isValid(m) || cur.cnt >= isVis[m]) continue;
q.add(new Subin(m,cur.cnt+1));
}
}
System.out.printf("%d\n%d",minCnt,cnt);
}
static boolean isValid(int x)
{
return x >= 0 && x < 100001;
}
}
📝 풀이
bfs문제입니다.
큐는 fifo구조이기 때문에, 시간 순서대로 숨바꼭질을 진행시킬 수 있습니다.
이를 활용하여 이동하다가 처음 동생을 마주친 순간을 최소값으로 정의해줍니다.
방문배열 isVis를 정수배열로 정의하여, 해당 위치에 도달했던 시점중 최소 시간값을 저장해두고, 그 시간보다 크다면 반복에서 제외해주는 방식을 사용했습니다.
예를들어 3이라는 위치에 처음 도달한 시간이 1초일때, 3에서 이동할 수 있는 위치는 이전과 동일하게 2,4,6이며 1초가 넘어가는 2초,3초 시점에서 3으로 넘어와봤자 이전보다 먼저 동생에게 도달할 경우의 수는 존재하지 않습니다.
위의 방식으로 조건에 부합하는 데이터만 큐에 담아주면 최솟값과 중복카운트를 얻어낼 수 있습니다.
📜 후기
이전에 풀었던 bfs문제들과 다르게 경우에 따라 중복을 허용해주어야하는 문제여서, 방문배열을 효율적으로 활용하는게 조금 헷갈렸던것 같아요 ㅠ
요즘 문제를 너무 편식하는것 같아서 친구가 골라준 문제랍니다 ㅋㅋㅋㅋㅋ
의외로 잘골라줘서 재밌게 풀었어요 ~.~
Author And Source
이 문제에 관하여(백준 12851 숨바꼭질2 (Java,자바)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@jh5253/백준-12851-숨바꼭질2-Java자바저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)