Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- KT
- COLAB
- filebeat
- docker
- image
- github
- KT인턴
- tensorflow2
- 개발자로드맵
- GIT
- 백준
- java
- 정보처리기사실기
- python3 #동적계획법 #permutations
- 안드로이드스튜디오
- logstash
- 호스팅
- YOLO
- elasticsearch
- kibana
- HAXM
- 계정 여러 개 동시 사용
- javascript #콜백함수 #비동기
- 2206
- 벽부수고이동하기
- container
Archives
- Today
- Total
코딩하고자용 블로그
[JAVA] 백준 2206번 - 벽 부수고 이동하기 본문
2206번: 벽 부수고 이동하기
N×M의 행렬로 표현되는 맵이 있다. 맵에서 0은 이동할 수 있는 곳을 나타내고, 1은 이동할 수 없는 벽이 있는 곳을 나타낸다. 당신은 (1, 1)에서 (N, M)의 위치까지 이동하려 하는데, 이때 최단 경로
www.acmicpc.net
최단경로 찾기 문제이며, 특이한 점은 한번 벽을 뚫을 수 있다는 것이다.
처음에는 부르트 포스로 접근하여, 한 벽 씩 뚫고 다시 메우면서 bfs를 돌리는 방법을 해보았다.
while(!queue.isEmpty()) {
int drillIdx[] = queue.poll();
map[drillIdx[0]][drillIdx[1]] = 0; //뚫고,
bq.offer(new int[]{0, 0, 1});
bfs();
map[drillIdx[0]][drillIdx[1]] = 1; //매꿔주고,
isVisit = new boolean[n][m]; // 초기화.
}
결과는 당연히 시간초과. (지금 생각하니 정말 비효율적..)
그래서 변화를 준 것이, 방문 여부 boolean 배열로 만들어서, 벽을 뚫을 때와, 벽을 뚫지 않았을 때 총 2가지 경우를 한번에 생각해줄 수 있도록 boolean 배열을 3차원 배열로 만들어주었다.
isVisit[r][c][0] = true;
isVisit[r][c][1] = true;
마지막 행의 인덱스가 0일 때는, 벽을 한 번도 뚫지 않았을 경우를, 1일 때는 벽을 한 번 뚫었을 경우를 처리해주는 식으로 문제를 풀 수 있었다.
아래는 최종 코드이다.
import java.io.*;
import java.util.*;
public class Main {
static int shortestPath = -1; //최단 경로 값.
static int[][] map;
static boolean[][][] isVisit;
static int n;
static int m;
static Queue<int[]> bq = new LinkedList<>(); //bfs 사용을 위한 큐.
public static void main(String[] args) throws IOException {
//Input
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
n = Integer.parseInt(st.nextToken());
m = Integer.parseInt(st.nextToken());
map = new int[n][m];
isVisit = new boolean[n][m][2];
for (int i = 0; i < n; i++) {
String s = br.readLine();
for (int j = 0; j < m; j++) {
map[i][j] = s.charAt(j) - '0';
}
}
//Processing
bq.offer(new int[]{0, 0, 1, 0});//행, 열, 이동 수, 벽뚫 여부
bfs();
//Output
System.out.println(shortestPath);
}
private static void bfs() {
isVisit[0][0][0] = true;
isVisit[0][0][1] = true;
while(!bq.isEmpty()) {
int[] nowIdx = bq.poll();
if(nowIdx[0] == n - 1 && nowIdx[1] == m - 1) { // 끝 지점 도달 시.
if (shortestPath == -1 || nowIdx[2] < shortestPath) {
shortestPath = nowIdx[2];
continue;
}
}
int dx[] = {1,0,-1,0};
int dy[] = {0,1,0,-1};
for (int i = 0; i < 4; i++) {
int nx = nowIdx[1] + dx[i];
int ny = nowIdx[0] + dy[i];
if(!(nx >= 0 && nx < m && ny >= 0 && ny < n)) continue;
if(map[ny][nx] == 1 && !isVisit[ny][nx][1] && nowIdx[3] == 0) { //길을 뚫어야 할 때.
isVisit[ny][nx][1] = true;
bq.offer(new int[] {ny, nx, nowIdx[2] + 1, nowIdx[3] + 1});
}
else if(map[ny][nx] == 0 && !isVisit[ny][nx][nowIdx[3]]) { //정상적인 경로.
isVisit[ny][nx][nowIdx[3]] = true;
bq.offer(new int[] {ny, nx, nowIdx[2] + 1, nowIdx[3]});
}
}
}
}
}
코드 지적은 항상 환영입니다 :)