본문 바로가기
공부/Algorithms w.Java

백준 2206; Java

by thegreatjy 2022. 1. 15.
728x90

 

https://www.acmicpc.net/problem/2206

 

2206번: 벽 부수고 이동하기

N×M의 행렬로 표현되는 맵이 있다. 맵에서 0은 이동할 수 있는 곳을 나타내고, 1은 이동할 수 없는 벽이 있는 곳을 나타낸다. 당신은 (1, 1)에서 (N, M)의 위치까지 이동하려 하는데, 이때 최단 경로

www.acmicpc.net

import java.util.*;
import java.io.*;

public class Main {
	static int N, M, ans;
	static int[][] accum, map;	//누적 공사 횟수 
	static int[] row= {0,0,1,-1};
	static int[] col= {1,-1,0,0};
	
	static class node{
		int x;
		int y;
		int length;
		int work;	//벽 공사 횟수 
		
		node(int x, int y, int length, int work){
			this.x=x; this.y=y;
			this.length=length;
			this.work=work;
		}
	}
	
	public static void bfs(int r, int c) {
		Queue<node> q=new LinkedList<>();
		q.offer(new node(r, c, 1, 0));
		accum[r][c]=0;
		
		while(!q.isEmpty()) {
			node nd=q.poll();
			
			if(nd.x==N && nd.y==M) {//도착 
				ans=nd.length;
				break;
			}
			
			for(int a=0;a<4;a++) {
				int nr=nd.x+row[a];
				int nc=nd.y+col[a];
				
				if(nr>0&&nr<=N&&nc>0&&nc<=M) {
					if(accum[nr][nc] > nd.work) {////현재 노드까지의 공사 횟수(0 || 1)<가볼 곳의 누적 공사 횟수(0 || 1 || max) 
						if(map[nr][nc]==0) {//벽이 없으면 
							accum[nr][nc]=nd.work;
							q.offer(new node(nr, nc, nd.length+1, nd.work));
						}else {//벽이 있음 
							if(nd.work==0) {//벽 공사를 한 적 없으면 
								accum[nr][nc]=nd.work+1;//갈 곳의 누적 공사 횟수를 늘려줌 
								q.offer(new node(nr, nc, nd.length+1, nd.work+1));
							}
						}
					}	
				}
			}
		}
		
	}
	
	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
		String str[]=br.readLine().split(" ");
		N=Integer.parseInt(str[0]);
		M=Integer.parseInt(str[1]);
		map=new int[N+1][M+1];
		accum=new int[N+1][M+1];
		
		for(int i=1;i<=N;i++) {
			str=br.readLine().split("");
			for(int j=1;j<=M;j++) {
				map[i][j]=Integer.parseInt(str[j-1]);
				accum[i][j]=Integer.MAX_VALUE;
			}
		}
		ans=Integer.MAX_VALUE;
		bfs(1,1);
		
		if(ans==Integer.MAX_VALUE)	System.out.println(-1);
		else	System.out.println(ans);
		
	}

}

 

최단 경로라서 backtracking && bfs 로 하다가 시간만 날렸네,,,ㅎㅎ 와~

 

https://kim6394.tistory.com/201

 

[백준 2206] 벽 부수고 이동하기 (Java, BFS)

[백준 2206] 벽 부수고 이동하기 (Java, BFS) 문제 출처 : 링크 2206번: 벽 부수고 이동하기 N×M의 행렬로 표현되는 맵이 있다. 맵에서 0은 이동할 수 있는 곳을 나타내고, 1은 이동할 수 없는 벽이

kim6394.tistory.com

..천재일까..? (오열)


사실 이해가 제대로 되진 않았다.. 대충 이해함.. 

 

accum[i][j]는 (1,1) ->(i, j)까지 누적 공사 횟수

node의 length는 (1,1)부터 현재 노드까지 경로 길이

node의 work는 (1,1)부터 현재 노드까지 공사 횟수

 

큐에서 뺀 노드를 현재 노드라고 한다. 그 노드의 사방위를 한 개씩(갈 노드) 검사한다.

갈 노드의 누적 공사 횟수(accum[nr][nc])는 0, 1, max 중 하나이다. 0 혹은 1이면 갈 노드가 한 번 이상 방문된 적이 있다는 의미이다.

현재 노드의 누적 공사 횟수(nd.work)는 0, 1 중 하나이다.

현재 노드의 누적 공사 횟수는 갈 노드의 누적 공사 횟수보다 작아야만(~방문한 적이 없어야지) 갈 노드로 전진이 가능하다.

 

이때, 현재 노드까지의 공사 횟수가 0, 갈 노드의 누적 공사 횟수가 1 인 경우는 갈 노드가 한 번 이상 방문한 적이 있다는 의미, 즉 다른 경로에 포함된 적이 있다는 것이다. 

 

그리고 도착한 노드의 길이가 왜 최단 거리인지 처음에 이해가 안되었는데, 이 부분은 트리를 그리면서 조금 이해가 됐다.. 

제일 빨리 도착하고 break;를 해서 탐색을 끝내버렸으니 그 노드의 길이가 최단 거리이다..

728x90

'공부 > Algorithms w.Java' 카테고리의 다른 글

백준 7569; Java  (0) 2022.01.17
백준 7576; Java  (0) 2022.01.16
백준 2573; Java  (0) 2022.01.13
프로그래머스 등굣길; Java  (0) 2022.01.11
백준 11967; Java  (1) 2022.01.11