BOJ_1261_알고스팟 (Java)
[Gold IV] 알고스팟 - 1261
성능 요약
메모리: 14776 KB, 시간: 124 ms
분류
0-1 너비 우선 탐색, 데이크스트라, 그래프 이론, 그래프 탐색, 최단 경로
제출 일자
2025년 2월 1일 21:27:46
문제 설명
알고스팟 운영진이 모두 미로에 갇혔다. 미로는 N*M 크기이며, 총 1*1크기의 방으로 이루어져 있다. 미로는 빈 방 또는 벽으로 이루어져 있고, 빈 방은 자유롭게 다닐 수 있지만, 벽은 부수지 않으면 이동할 수 없다.
알고스팟 운영진은 여러명이지만, 항상 모두 같은 방에 있어야 한다. 즉, 여러 명이 다른 방에 있을 수는 없다. 어떤 방에서 이동할 수 있는 방은 상하좌우로 인접한 빈 방이다. 즉, 현재 운영진이 (x, y)에 있을 때, 이동할 수 있는 방은 (x+1, y), (x, y+1), (x-1, y), (x, y-1) 이다. 단, 미로의 밖으로 이동 할 수는 없다.
벽은 평소에는 이동할 수 없지만, 알고스팟의 무기 AOJ를 이용해 벽을 부수어 버릴 수 있다. 벽을 부수면, 빈 방과 동일한 방으로 변한다.
만약 이 문제가 알고스팟에 있다면, 운영진들은 궁극의 무기 sudo를 이용해 벽을 한 번에 다 없애버릴 수 있지만, 안타깝게도 이 문제는 Baekjoon Online Judge에 수록되어 있기 때문에, sudo를 사용할 수 없다.
현재 (1, 1)에 있는 알고스팟 운영진이 (N, M)으로 이동하려면 벽을 최소 몇 개 부수어야 하는지 구하는 프로그램을 작성하시오.
입력
첫째 줄에 미로의 크기를 나타내는 가로 크기 M, 세로 크기 N (1 ≤ N, M ≤ 100)이 주어진다. 다음 N개의 줄에는 미로의 상태를 나타내는 숫자 0과 1이 주어진다. 0은 빈 방을 의미하고, 1은 벽을 의미한다.
(1, 1)과 (N, M)은 항상 뚫려있다.
출력
첫째 줄에 알고스팟 운영진이 (N, M)으로 이동하기 위해 벽을 최소 몇 개 부수어야 하는지 출력한다.
문제 풀이
다익스트라 문제다. breakCnt를 우선순위로 정렬기준을 삼아 PriorityQueue를 사용했다. 경계처리를 편하게 하기 위해 padding처리도 1-로 해 주었다.
코드
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
package BOJ_1261_알고스팟;
/**
* Author: nowalex322, Kim HyeonJae
*/
import java.io.*;
import java.util.*;
public class Main {
static class Node implements Comparable<Node>{
int r, c, breakCnt;
public Node(int r, int c, int breakCnt) {
this.r = r;
this.c = c;
this.breakCnt = breakCnt;
}
@Override
public int compareTo(Node o){
return this.breakCnt - o.breakCnt;
}
}
static BufferedReader br;
static BufferedWriter bw;
static StringTokenizer st;
static int N, M, board[][], dr[] = {-1, 1, 0, 0}, dc[] = {0, 0 ,-1, 1};
static boolean visited[][];
public static void main(String[] args) throws Exception {
new Main().solution();
}
public void solution() throws Exception {
// br = new BufferedReader(new InputStreamReader(System.in));
br = new BufferedReader(new InputStreamReader(new FileInputStream("src/main/java/BOJ_1261_알고스팟/input.txt")));
bw = new BufferedWriter(new OutputStreamWriter(System.out));
st = new StringTokenizer(br.readLine());
M = Integer.parseInt(st.nextToken());
N = Integer.parseInt(st.nextToken());
board = new int[N+2][M+2];
visited = new boolean[N+2][M+2];
// padding with -1
for(int i = 0; i <= M+1; i++) {
board[0][i] = -1;
board[N+1][i] = -1;
}
for(int i = 0; i <= N+1; i++) {
board[i][0] = -1;
board[i][M+1] = -1;
}
for(int i = 1; i < N+1; i++){
String line = br.readLine();
for(int j = 1; j < M+1; j++){
board[i][j] = line.charAt(j-1) - '0';
}
}
int res = bfs(1, 1);
bw.write(String.valueOf(res));
bw.flush();
bw.close();
br.close();
}
private int bfs(int r, int c) {
PriorityQueue<Node> pq = new PriorityQueue<>();
pq.offer(new Node(r, c, 0));
visited[r][c] = true;
while(!pq.isEmpty()){
Node currNode = pq.poll();
if(currNode.r == N && currNode.c == M) return currNode.breakCnt;
for(int k=0; k<4; k++){
int nextR = currNode.r + dr[k];
int nextC = currNode.c + dc[k];
int currBreakCnt = currNode.breakCnt;
if(board[nextR][nextC] == -1) continue;
if(!visited[nextR][nextC] && board[nextR][nextC] == 0){
pq.offer(new Node(nextR, nextC, currBreakCnt));
visited[nextR][nextC] = true;
}
if(!visited[nextR][nextC] && board[nextR][nextC] == 1){
pq.offer(new Node(nextR, nextC, currBreakCnt+1));
visited[nextR][nextC] = true;
}
}
}
return 0;
}
}
다시 풀어본 코드
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
/**
* Author: nowalex322, Kim HyeonJae
*/
import java.io.*;
import java.util.*;
public class Main {
static BufferedReader br;
static BufferedWriter bw;
static StringTokenizer st;
static int N, M;
static int[] dr = {-1, 1, 0, 0}, dc = {0, 0, -1, 1};
public static void main(String[] args) throws Exception {
new Main().solution();
}
class Node implements Comparable<Node> {
int r, c, breakCnt;
public Node(int r, int c, int breakCnt){
this.r = r;
this.c = c;
this.breakCnt = breakCnt;
}
public int compareTo(Node o) {
return this.breakCnt - o.breakCnt;
}
}
public void solution() throws Exception {
br = new BufferedReader(new InputStreamReader(System.in));
// br = new BufferedReader(new InputStreamReader(new FileInputStream("src/main/java/BOJ_1261_알고스팟/input.txt")));
bw = new BufferedWriter(new OutputStreamWriter(System.out));
st = new StringTokenizer(br.readLine());
M = Integer.parseInt(st.nextToken());
N = Integer.parseInt(st.nextToken());
int[][] board = new int[N][M];
for(int i = 0; i < N; i++){
String line = br.readLine();
for(int j = 0; j < M; j++){
board[i][j] = line.charAt(j) - '0';
}
}
PriorityQueue<Node> pq = new PriorityQueue<>();
boolean[][] visited = new boolean[N][M];
pq.add(new Node(0, 0, 0));
visited[0][0] = true;
int res = 0;
while(!pq.isEmpty()){
Node curr = pq.poll();
if(curr.r == N-1 && curr.c == M-1) {
res = curr.breakCnt;
System.out.println(res);
return;
}
for(int k=0; k < 4; k++){
int nr = curr.r + dr[k];
int nc = curr.c + dc[k];
if(isValid(nr, nc) && !visited[nr][nc]){
if(board[nr][nc] == 0){
pq.add(new Node(nr, nc, curr.breakCnt));
}
else{
pq.add(new Node(nr, nc, curr.breakCnt + 1));
}
visited[nr][nc] = true;
}
}
}
}
private boolean isValid(int r, int c){
return r >= 0 && r < N && c >= 0 && c < M;
}
}