반응형
문제 설명
2151번: 거울 설치
첫째 줄에 집의 크기 N (2 ≤ N ≤ 50)이 주어진다. 다음 N개의 줄에는 N개의 문자로 집에 대한 정보가 주어진다. ‘#’는 문이 설치된 곳으로 항상 두 곳이며, ‘.’은 아무 것도 없는 것으로 빛은
www.acmicpc.net
한 쪽 문(#)에서 다른 쪽 문(#)으로 빛이 가는 경로를 만들기 위해 ! 가 위치한 자리에 거울을 / 모양 또는 \모양으로 설치하는 문제이다.
문제 풀이
처음에는 ! 를 0개 ~ !의 개수만큼 뽑는 조합을 이용해 거울을 위치시키고 빛이 이동하는 시뮬레이션을 그려 반대 문에 도달하는 방식으로 구현하였다.
접근 방법이 틀린 것 같아 다시 구상했다. bfs와 우선순위큐를 이용해 !를 만날 때마다 직진, 좌회전, 우회전을 하고, 좌회전과 우회전일 경우에는 거울 개수 + 1 을 수행했다. 방문처리는 같은 자리에 같은 방향으로 도착한 적이 있다면 제외하는 방식으로, 3차원 boolean 배열을 이용했다. 이 방식으로 다시 구현해 통과했다.
문제 풀이 코드
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.PriorityQueue;
public class _2151_거울설치 {
static class Node implements Comparable<Node>{
int r, c;
int dir; //방향
int count = 0; //거울 개수
Node(int r, int c) {
this.r = r;
this.c = c;
}
Node(int r, int c,int dir) {
this.r = r;
this.c = c;
this.dir = dir;
}
Node(int r, int c,int dir,int count) {
this.r = r;
this.c = c;
this.dir = dir;
this.count = count;
}
@Override
public int compareTo(Node o) {
// TODO Auto-generated method stub
return this.count - o.count;
}
}
static int N;
static char[][] map;
static int dr[] = { -1, 0, 1, 0 }; // 상,우,하,좌
static int dc[] = { 0, -1, 0, 1 };
static boolean visited[][][];
public static void main(String[] args) throws NumberFormatException, IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
N = Integer.parseInt(in.readLine());
map = new char[N][];
visited= new boolean[N][N][4];
Node startDoor = null; //시작할 #
for (int i = 0; i < N; ++i) {
map[i] = in.readLine().toCharArray();
for (int j = 0; j < N; ++j) {
if (map[i][j] == '#') {
startDoor = new Node(i, j);
}
}
}
PriorityQueue<Node> pQueue = new PriorityQueue<>();
for(int i = 0; i<4;++i) { //시작 문에 4가지 방향으로 큐에 넣기
pQueue.offer(new Node(startDoor.r,startDoor.c,i));
visited[startDoor.r][startDoor.c][i] = true;
}
int answer = 0;
loop:while(!pQueue.isEmpty()) {
Node n = pQueue.poll();
int rr = n.r + dr[n.dir];
int cc = n.c + dc[n.dir];
if(rr < 0|| cc< 0|| rr>= N||cc>=N) //범위 밖에 나가면
continue;
if(visited[rr][cc][n.dir]) //같은 위치에 같은 방향으로 방문한 적이 있다면
continue;
switch(map[rr][cc]) {
case '.': //가던 방향 그대로
pQueue.offer(new Node(rr,cc,n.dir,n.count));
visited[rr][cc][n.dir] = true;
break;
case '!': //직진, 좌회전, 우회전
pQueue.offer(new Node(rr,cc,n.dir,n.count));
pQueue.offer(new Node(rr,cc,(n.dir+1)%4,n.count+1));
pQueue.offer(new Node(rr,cc,(n.dir+3)%4,n.count+1));
visited[rr][cc][n.dir] = true;
visited[rr][cc][(n.dir+1)%4] = true;
visited[rr][cc][(n.dir+3)%4] = true;
break;
case '#': //도착
answer = n.count;
break loop;
}
}
System.out.println(answer);
}
}
반응형
'알고리즘 문제풀이 > 백준' 카테고리의 다른 글
Baekjoon_1541_잃어버린 괄호 (0) | 2020.12.15 |
---|---|
Baekjoon_2217_로프 (0) | 2020.12.15 |
Baekjoon_1074_Z (0) | 2020.12.14 |
Baekjoon_20303_할로윈의 양아치 (0) | 2020.12.10 |
Baekjoon_20208_진우의 민트초코우유 (0) | 2020.12.09 |