티스토리 뷰
https://www.acmicpc.net/problem/18224
18224번: 미로에 갇힌 건우
건우가 가장 빨리 탈출할 수 있는 날이 몇번째 날인지, 그리고 낮이면 "sun", 밤이면 "moon"을 공백으로 구분하여 함께 출력한다. 예를 들어, 2번째 날 밤일 경우, "2 moon" 을 출력하고, 3번째 날 낮
www.acmicpc.net
문제
평소 탱자탱자 놀던 건우가 마지막 날에 과제를 시작했다. 건우는 피곤이 몰려왔는지, 그만 잠이 들고 말았다! 그러고는 꿈을 꿨다. 그곳은 미로였는데 너무 현실성이 없었던 탓에 건우는 꿈이란 걸 알아챘다. 얼른 꿈에서 깨려고 노력했지만 깰 수 없었다. 왜냐하면 건우가 꿈에서 깨어나려면 반드시 미로를 탈출해야만 했기 때문이다. 미로의 특징은 다음과 같다.
- n×n미로이며 가장 왼쪽 위가 출발지, 가장 오른쪽 아래가 도착지이다. 출발지와 도착지에는 벽이 없음이 보장된다.
- 건우는 상하좌우로만 움직일 수 있으며, 벽을 넘는 것을 제외하면 한 번 이동할 때 벽이 없는 인접한 칸으로 이동한다.
- 초기 상태는 첫 번째 날 낮으로 시작하고, 건우가 m번 이동할 때 마다 낮에서 밤 또는 밤에서 낮으로 바뀐다.
- 밤에는 낮과 달리 추가로 벽을 넘을 수 있다. 벽을 넘을 때는 가려는 방향의 인접한 칸에 벽이 있어야 하며, 건우가 서 있을 수 있는 칸이 나올때까지 연속된 벽을 넘는다.
- 벽을 넘는 도중에 방향을 바꿀 순 없으며, 벽을 넘으면 1번 이동한 것으로 간주한다.
위 경우처럼 벽을 넘었을 때 미로를 벗어날 경우에는 이동할 수 없다.
건우가 가장 빨리 탈출할 수 있는 날이 몇 번째 날의 낮 혹은 밤인지를 구해서 건우가 잠에서 깨도록 만들자!
유형 : BFS
접근 방식
- 해당 문제를 해결하기 위해 가장 중요한 것은 방문 배열을 어떻게 선언하는가이다.
- 방문 배열에 있어 고려해야 할 요소는 2가지이다.
- 낮인가 ? , 밤인가 ?
- 움직임이 몇번 이루어졌는가?
- 메모리 초과를 고려해서 boolean 배열로 선언해야 한다.
- 방문 배열에 있어 고려해야 할 요소는 2가지이다.
전체 코드
import java.util.*;
import java.io.*;
public class Main {
static int resultDay = -1;
static int isSun = 0;
static int n,m;
static int[][] board;
static int[] dx = {0,0,-1,1};
static int[] dy = {1,-1,0,0};
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());
m = Integer.parseInt(st.nextToken());
board = new int[n+1][n+1];
for(int i = 1 ; i <= n ; i++){
st = new StringTokenizer(br.readLine()," ");
for(int j = 1 ; j <= n ; j++){
board[i][j] = Integer.parseInt(st.nextToken());
}
}
bfs();
if(resultDay == -1){
System.out.println(-1);
}else{
System.out.println(resultDay+" "+(isSun == 0 ? "sun" : "moon"));
}
br.close();
}
static void bfs(){
PriorityQueue<Node> pq = new PriorityQueue<>(
(x,y) -> {
if(x.day == y.day){
if(x.isDay == y.isDay){
return x.move - y.move;
}
return x.isDay - y.isDay;
}
return x.day - y.day;
}
);
pq.add(new Node(1,1,1,0,0));
boolean[][][][] v = new boolean[n+1][n+1][2][m+1];
v[1][1][0][0] = true;
while(!pq.isEmpty()){
Node cur = pq.poll();
if(cur.x == n && cur.y == n){
if(resultDay == -1 || resultDay > cur.day){
resultDay = cur.day;
isSun = cur.isDay;
}
else if(resultDay == cur.day){
if(isSun == 1){
isSun = cur.isDay;
}
}
break;
}
if(cur.isDay == 0){
for(int i = 0 ; i < 4 ; i++){
int nx = cur.x + dx[i];
int ny = cur.y + dy[i];
if(isOut(nx,ny))
continue;
if(board[nx][ny] == 1)
continue;
int tmpMove = cur.move + 1;
if(tmpMove == m){
if(!v[nx][ny][1][0]){
v[nx][ny][1][0] = true;
pq.add(new Node(nx,ny,cur.day,0,1));
}
}else{
if(!v[nx][ny][0][tmpMove]){
v[nx][ny][0][tmpMove] = true;
pq.add(new Node(nx,ny,cur.day,tmpMove,0));
}
}
}
}else{
for(int i = 0 ; i < 4 ; i++){
int nx = cur.x + dx[i];
int ny = cur.y + dy[i];
if(isOut(nx,ny))
continue;
int tmpMove = cur.move + 1;
if(board[nx][ny] == 0){
if(tmpMove == m){
if(!v[nx][ny][0][0]){
v[nx][ny][0][0] = true;
pq.add(new Node(nx,ny,cur.day + 1,0,0));
}
}else{
if(!v[nx][ny][1][tmpMove]){
v[nx][ny][1][tmpMove] = true;
pq.add(new Node(nx,ny,cur.day,tmpMove,1));
}
}
}else{
int idx = findJump(nx,ny,i);
if(idx == -1)
continue;
nx = nx + idx*dx[i];
ny = ny + idx*dy[i];
if(tmpMove == m){
if(!v[nx][ny][0][0]){
v[nx][ny][0][0] = true;
pq.add(new Node(nx,ny,cur.day + 1,0,0));
}
}else{
if(!v[nx][ny][1][tmpMove]){
v[nx][ny][1][tmpMove] = true;
pq.add(new Node(nx,ny,cur.day,tmpMove,1));
}
}
}
}
}
}
}
static int findJump(int x,int y,int dir){
int idx = 1;
while(true){
int nx = x + idx*dx[dir];
int ny = y + idx*dy[dir];
if(isOut(nx,ny)){
break;
}
if(board[nx][ny] == 0){
return idx;
}
idx++;
}
return -1;
}
static boolean isOut(int x,int y){
if(x < 1 || x > n || y < 1 || y > n)
return true;
return false;
}
static class Node{
int x;
int y;
int day;
int move;
int isDay;
Node(int x,int y,int day,int move,int isDay){
this.x = x;
this.y = y;
this.day = day;
this.move = move;
this.isDay = isDay;
}
}
}
'알고리즘 > 백준' 카테고리의 다른 글
백준 2632 (피자판매) - java (0) | 2024.04.15 |
---|---|
백준 17143 (낚시왕) - java (0) | 2024.04.02 |
백준 12763 (지각하면 안 돼) - java (0) | 2024.03.27 |
백준 22868 산책 (small) (0) | 2024.03.25 |
백준 1486 (등산) - java (0) | 2024.03.18 |
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- 백준 #1987 #알파벳 #자바 #java
- 백준 #16973 #직사각형 탈출
- 백준 #3980 #선발 명단
- 백준 #13549 #숨바꼭질3
- 백준 #2580 #스도쿠
- 백준 #12014 #주식 #자바 #java
- 17218
- 백준 #4963 #섬의 개수
- 백준 #25603 #짱해커 이동식 #java #자바
- 백준
- 17394
- 백준 #25195 #yes or yes #java #자바
- 백준 #치즈 #2638
- 자바 #JAVA
- 백준 #18405 #경쟁적 전염
- 백준 #15686 #치킨 배달
- 백준 #1325 #효율적인 해킹
- 백준 #다리 만들기 #2146
- 백준 #28140 #빨강~ 빨강~ 파랑! 파랑! 달콤한 솜사탕! #java #자바
- 백준 #
- 자바
- 백준 #1584 #게임 #java #자바
- 백준 #1759 #암호 만들기
- 백준 #인구 이동 #16234
- 백준 #5721 #사탕 줍기 대회 #java #자바
- Java
- 백준 #14863 #서울에서 경산까지 #java #자바
- 백준 #17940 #주식 #자바 #java
- 백준 #2636 #치즈
- 백준 #1727 #커플 만들기 #자바 #java
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 |
글 보관함