문제
https://www.acmicpc.net/problem/1194
풀이(40분)
import java.io.*;
import java.util.*;
public class Main {
static int n, m;
static char[][] map;
static Node start;
static int[] dx = {0, 1, 0, -1}; // 사방탐색
static int[] dy = {1, 0, -1, 0};
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
st = new StringTokenizer(br.readLine());
n = Integer.parseInt(st.nextToken());
m = Integer.parseInt(st.nextToken());
map = new char[n][m];
for(int i = 0; i < n; i++) {
String input = br.readLine();
for(int j = 0; j < m; j++) {
char c = input.charAt(j);
map[i][j] = c;
if(c == '0') start = new Node(i, j, 0, 0);
}
}
System.out.println(bfs());
}
public static int bfs() {
Queue<Node> q = new LinkedList<>();
boolean[][][] visited = new boolean[n][m][64]; // 열쇠를 기준으로 한 방문 체크
q.offer(start);
visited[start.x][start.y][0] = true;
while(!q.isEmpty()) {
Node cur = q.poll();
if(map[cur.x][cur.y] == '1') return cur.cost;
for(int i = 0; i < 4; i++) {
int nextX = cur.x + dx[i];
int nextY = cur.y + dy[i];
if(!isInBounds(nextX, nextY)) continue;
if(visited[nextX][nextY][cur.key] || map[nextX][nextY] == '#') continue;
if(map[nextX][nextY] >= 'a' && map[nextX][nextY] <= 'f') { //열쇠
int next_key = 1 << (map[nextX][nextY] - 'a'); // 값의 크기에 따른 비트 이동
next_key = cur.key | next_key; // or 연산
visited[nextX][nextY][next_key] = true;
q.offer(new Node(nextX, nextY, cur.cost + 1, next_key));
}
else if(map[nextX][nextY] >= 'A' && map[nextX][nextY] <= 'F') { //문
if((cur.key & 1 << (map[nextX][nextY] - 'A')) == (int)Math.pow(2, map[nextX][nextY] - 'A')) { // 비트의 상태 확인
visited[nextX][nextY][cur.key] = true;
q.offer(new Node(nextX, nextY, cur.cost + 1, cur.key));
}
} else {
visited[nextX][nextY][cur.key] = true;
q.offer(new Node(nextX, nextY, cur.cost + 1, cur.key));
}
}
}
return -1;
}
static boolean isInBounds(int row, int col){
return row >= 0 && row < n && col >= 0 && col < m;
}
public static class Node {
int x, y, cost, key;
public Node(int x, int y, int cost, int key) {
this.x = x;
this.y = y;
this.cost = cost;
this.key = key;
}
}
}
문제 풀이 전략
문제 풀이 초기에는 열쇠에 대한 정보를 집합을 통해 관리하며 이를 전달하도록 생각하였다.
하지만 bfs가 반복될수록 생성되는 집합에 대한 낭비가 심해졌다.
그렇기에 비트마스킹이라는 아이디어를 떠올릴 수 있었다.
2의 지수를 이용하여 비트마스킹 하는 전략과 and, or 연산을 적절히 활용한다면 키에 대한 관리가 명확하게 될 수 있을 것이라고 생각했다.
최종적으로 bfs + 비트마스킹을 통해 문제를 해결할 수 있었다!
'문제 풀이 > 백준' 카테고리의 다른 글
[백준] 6118번. 숨박꼭질(JAVA) (0) | 2025.06.11 |
---|---|
[백준] 2836번. 수상 택시(JAVA) (1) | 2025.06.10 |
[백준] 2186번. 문자판(JAVA) (0) | 2025.06.10 |
[백준] 2468번. 안전 영역(JAVA) (1) | 2025.06.10 |
[백준] 1522번. 문자열 교환(JAVA) (1) | 2025.06.10 |