2151번: 거울 설치
첫째 줄에 집의 크기 N (2 ≤ N ≤ 50)이 주어진다. 다음 N개의 줄에는 N개의 문자로 집에 대한 정보가 주어진다. ‘#’는 문이 설치된 곳으로 항상 두 곳이며, ‘.’은 아무 것도 없는 것으로 빛은
www.acmicpc.net
문제 읽기
처음에 문제를 읽었을 때에는 dfs를 써야겠다고 생각했다. 그렇게 풀었는데 백트래킹을 제대로 하지 않아서 인지.. 3%에서 계속 시간 초과가 났다 !! 너무 답답해서 그냥 풀이 방식을 바꿔보기로 했다.
글 읽기 - 어디가 틀렸을까요 ㅠ
댓글을 작성하려면 로그인해야 합니다.
www.acmicpc.net
위 글을 통해 힌트를 얻었다. 0-1 BFS를 이용하면 될 것 같았다. 잊고 있었던 알고리즘이다.
문제 풀기
0-1 BFS는 BFS처럼 방문하면서, Deque를 이용하여 방문 비용이 증가하면 뒤에 넣고, 그대로이면 앞에 넣으며 이동한다. 또한 방문 체크를 덱에서 꺼낼 때 하기 때문에 같은 지점에 대해서 여러 번 값을 덱에 넣어 두고, 그 중에서 최소 비용으로 방문할 수 있다. (즉, 중복 방문이 가능하며, 그 중 최솟값을 저장할 수 있는 방식이다.) 이 특징은 다익스트라와 유사하다.
사실 다익스트라와 0-1 BFS는 진짜 한 끗 차이라 생각한다.. 진짜 비슷하다. 차이점은 방문 체크, 자료구조, 삽입 방식 뿐이다.
처음에는 중복 방문 때문에 DFS가 더 와 닿았는데, 최소 비용이기 때문에 DFS보다는 BFS를 하는 게 훨씬 효율적이라는 생각이 든다.
다익스트라에 대한 자세한 설명을 보고 싶으면 아래 링크를 방문하면 된다.
다익스트라, Dijkstra Algorithm
코딩 문제에서 많이 볼 수 있는 그래프와 관련된 알고리즘을 공부해보자. 그래프에서 최단 거리를 구하는 알고리즘은 다음과 같은 것들이 있다. 💡 그래프의 최단 거리 구하는 알고리즘 1. 다익
rue-mi.tistory.com
0-1 BFS에 대한 자세한 설명을 보고 싶으면 아래 링크를 방문하면 된다.
0-1 BFS
0-1 BFS란? 💡 0-1 BFS 가중치가 0 또는 1로만 주어진 그래프에서, 시작 노드가 주어졌을 때 다른 모든 노드로의 최단 경로를 찾고자 할 때 사용하는, BFS를 응용한 알고리즘이다. 보편적으로 그래프
rue-mi.tistory.com
사실 원래 0-1 BFS는 비용이 갱신 되는 경우에만 방문하기 때문에 따로 방문 체크를 하지 않아도 별 문제는 없었다. 하지만 이 문제의 경우에는 따로 갱신할 비용이 없기 때문에 방문 처리를 해주는 식으로 메모리와 시간을 줄였다. (어찌 보면 다익스트라에 더 가까울지도)
코드
package ps.ㄱSolving;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayDeque;
import java.util.Deque;
public class BOJ_G3_2151_거울설치 {
static class Pos{
int r, c;
int cnt;
int dir;
public Pos(int r, int c, int cnt, int dir){
this.r = r;
this.c = c;
this.cnt = cnt;
this.dir = dir;
}
}
static int N;
static char[][] map;
static boolean[][][] visited;
static int startR = -1, startC, endR, endC;
static int[] dr = {-1, 0, 1, 0};//상0좌1하2우3 -> 0101
static int[] dc = {0, -1, 0, 1};
public static void main(String[] args) throws IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
N = Integer.parseInt(in.readLine());
map = new char[N][N];
for (int i = 0; i < N; i++){
map[i] = in.readLine().toCharArray();
for (int j = 0; j < N; j++){
if (map[i][j] == '#'){
if (startR == -1){
startR = i;
startC = j;
}
else{
endR = i;
endC = j;
}
}
}
}
Deque<Pos> dec = new ArrayDeque<>();
visited = new boolean[N][N][4];
for (int di = 0; di < 4; di++){
int nr = startR + dr[di];
int nc = startC + dc[di];
if (nr < 0 || nr >= N || nc < 0 || nc >= N || map[nr][nc] == '*') continue;
dec.offer(new Pos(nr, nc, 0, di));
}
while(!dec.isEmpty()){
Pos cur = dec.pollFirst();
// System.out.println(cur.r + " " + cur.c);
if (visited[cur.r][cur.c][cur.dir]) continue;
visited[cur.r][cur.c][cur.dir] = true;
if (cur.r == endR && cur.c == endC){
System.out.println(cur.cnt);
break;
}
else if (map[cur.r][cur.c] == '.'){
//직진
int nr = cur.r + dr[cur.dir];
int nc = cur.c + dc[cur.dir];
if (nr < 0 || nr >= N || nc < 0 || nc >= N || map[nr][nc] == '*') continue;
dec.offerFirst(new Pos(nr, nc, cur.cnt, cur.dir));
}
else { //느낌표인 경우 -> 3방향
for (int di = 0; di < 4; di++){
if (di == (cur.dir + 2)%4) continue;
int nr = cur.r + dr[di];
int nc = cur.c + dc[di];
if (nr < 0 || nr >= N || nc < 0 || nc >= N || map[nr][nc] == '*') continue;
if (di == cur.dir){
dec.offerFirst(new Pos(nr, nc, cur.cnt, cur.dir));
}
else{
dec.offerLast(new Pos(nr, nc, cur.cnt+1, di));
}
}
}
}
}
}
'Algorithm > Graph Search Algorithm' 카테고리의 다른 글
BOJ G4 1956 운동 JAVA (0) | 2024.02.27 |
---|---|
BOJ G3 16954 움직이는 미로 탈출 JAVA (0) | 2024.02.20 |
BOJ G4 11404 플로이드 JAVA (0) | 2024.02.17 |
Floyd-Warshall, 플로이드 워샬 알고리즘 (0) | 2024.02.17 |
BOJ G2 2931 가스관 JAVA (0) | 2024.02.16 |