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

 

2206번: λ²½ λΆ€μˆ˜κ³  μ΄λ™ν•˜κΈ°

NΓ—M의 ν–‰λ ¬λ‘œ ν‘œν˜„λ˜λŠ” 맡이 μžˆλ‹€. λ§΅μ—μ„œ 0은 이동할 수 μžˆλŠ” 곳을 λ‚˜νƒ€λ‚΄κ³ , 1은 이동할 수 μ—†λŠ” 벽이 μžˆλŠ” 곳을 λ‚˜νƒ€λ‚Έλ‹€. 당신은 (1, 1)μ—μ„œ (N, M)의 μœ„μΉ˜κΉŒμ§€ μ΄λ™ν•˜λ € ν•˜λŠ”λ°, μ΄λ•Œ μ΅œλ‹¨ 경둜

www.acmicpc.net

 

 

 

 

 

 

문제

  • NΓ—M의 ν–‰λ ¬λ‘œ ν‘œν˜„λ˜λŠ” 맡이 μžˆλ‹€. λ§΅μ—μ„œ 0은 이동할 수 μžˆλŠ” κ³³, 1은 벽이 μžˆλŠ” 곳을 λ‚˜νƒ€λ‚Έλ‹€.
  • (1, 1)μ—μ„œ (N, M)의 μœ„μΉ˜κΉŒμ§€ μ΄λ™ν•˜λ € ν•˜λŠ”λ°, μ΅œλ‹¨ 경둜둜 μ΄λ™ν•˜λ € ν•œλ‹€.
    • ν•œ μΉΈμ—μ„œ 이동할 수 μžˆλŠ” 칸은 μƒν•˜μ’Œμš°λ‘œ μΈμ ‘ν•œ μΉΈ
  • ν•œ 개의 벽을 λΆ€μˆ˜κ³  μ΄λ™ν•˜λŠ” 것이 μ’€ 더 κ²½λ‘œκ°€ 짧아진닀면, 벽을 ν•œ 개 κΉŒμ§€ λΆ€μˆ˜κ³  μ΄λ™ν•˜μ—¬λ„ λœλ‹€.
  • 첫째 쀄에 μ΅œλ‹¨ 거리λ₯Ό 좜λ ₯ν•œλ‹€. λΆˆκ°€λŠ₯ν•  λ•ŒλŠ” -1을 좜λ ₯ν•œλ‹€.

 

 

 

 

 

풀이

μƒν•˜μ’Œμš° μΈμ ‘ν•œ 칸으둜 ν•œ μΉΈμ”© μ΄λ™ν–ˆμ„ λ•Œμ˜ μ΅œλ‹¨ 경둜λ₯Ό κ΅¬ν•˜λŠ” 문제둜, ν•œ μΉΈμ”© μ΄λ™ν•˜λ©° 사방탐색을 톡해 λͺ¨λ“  경우의 μˆ˜μ— λŒ€ν•΄ μ‚΄ν”Όκ³  λͺ©ν‘œ 지점에 λ„λ‹¬ν–ˆμ„μ‹œ 탐색을 μ’…λ£Œν•΄μ•Ό ν•œλ‹€. λ”°λΌμ„œ 큐λ₯Ό μ΄μš©ν•œ BFS μ•Œκ³ λ¦¬μ¦˜μ„ μ‚¬μš©ν•˜μ—¬ 문제λ₯Ό ν’€μ—ˆλ‹€.

 

전체적인 ν’€μ΄λŠ” λ‹€λ₯Έ μ΅œλ‹¨ 경둜λ₯Ό κ΅¬ν•˜λŠ” λ¬Έμ œμ™€ κ°™μ§€λ§Œ, '벽을 ν•œ 개 κΉŒμ§€ λΆ€μˆ˜κ³  이동할 수 μžˆλ‹€'λΌλŠ” 쑰건이 λΆ™μœΌλ©΄μ„œ 풀이가 달라진닀.

 

탐색을 ν•  λ•Œ, 벽을 λΆ€μ‰ˆλŠ”μ§€μ— 따라 이동이 λ‹¬λΌμ§€κ²Œ λœλ‹€. λ”°λΌμ„œ νμ— μ’Œν‘œ 정보λ₯Ό 넣을 λ•Œ, ν–‰λ ¬ μ’Œν‘œκ°’, 이동 거리뿐만 μ•„λ‹ˆλΌ μ§€κΈˆκΉŒμ§€ 벽을 λΆ€μˆœμ μ΄ μžˆλŠ”μ§€ 정보λ₯Ό μ €μž₯ν•  ν•„μš”κ°€ μžˆλ‹€. λ”°λΌμ„œ μ’Œν‘œ 정보λ₯Ό λ‹΄λŠ” PointλΌλŠ” 객체에 boolean ν˜•μ˜ λ³€μˆ˜(hit)을 좔가해쀬닀.

 

  • 벽이 μ•„λ‹˜
    • 벽을 λΆ€μˆœμ μ΄ μžˆλ‹€ -> κ·ΈλŒ€λ‘œ 탐색
    • 벽을 λΆ€μˆœμ μ΄ μ—†λ‹€ -> κ·ΈλŒ€λ‘œ 탐색
  • 벽이닀
    • 벽을 λΆ€μˆœμ μ΄ μ—†λ‹€ -> 벽을 λΆ€μˆ˜κ³  탐색
    • 벽을 λΆ€μˆœμ μ΄ μžˆλ‹€ -> 더이상 탐색 X

 

 

 

μ΄λŒ€λ‘œ 채점을 λŒλ Έλ”λ‹ˆ ν‹€λ Έλ‹€. 예제 μž…μΆœλ ₯의 ν…ŒμŠ€νŠΈμΌ€μ΄μŠ€λŠ” λͺ¨λ‘ ν†΅κ³Όν•˜λŠ”λ°, λ°±μ€€ 문제 λ‚΄ κ²Œμ‹œνŒμ— μžˆλŠ” λ°˜λ‘€λ₯Ό λ³΄λ‹ˆ ν‹€λ¦° 원인을 찾을 수 μžˆμ—ˆλ‹€. (λ°˜λ‘€ : https://www.acmicpc.net/board/view/119335)

 

 

방문체크λ₯Ό 2μ°¨μ›μ˜ boolean λ°°μ—΄λ‘œ ν•΄λ‹Ή 칸의 ν–‰λ ¬ μ’Œν‘œκ°’μœΌλ‘œ 체크λ₯Ό ν•΄μ£Όκ³  μžˆμ—ˆλŠ”λ°, 이 λΆ€λΆ„μ—μ„œ ν‹€λ¦° 것을 λ°œκ²¬ν•  수 μžˆμ—ˆλ‹€. 이전에 벽을 λΆ€μˆ˜κ³  갔을 λ•Œ, 방문체크가 λ˜μ–΄ λ‚˜μ€‘μ— 벽을 λΆ€μˆ˜μ§€ μ•Šκ³  ν•΄λ‹Ή 지점에 λ„λ‹¬ν•˜κ²Œ λ˜λ”λΌλ„ 이미 방문체크가 λ˜μ–΄ 더이상 탐색을 ν•  수 μ—†κ²Œ λœλ‹€. λ¨Όμ € 벽을 λΆ€μˆ˜κ³  κ°”λ˜ κ²½λ‘œκ°€ μ΅œλ‹¨ 거리일 μˆ˜λ„ μžˆμ§€λ§Œ, ν›„에 λ‹€λ₯Έ μ§€μ μ—μ„œ λ§‰νžˆκ²Œ λ˜μ–΄ λ„μ°©ν•˜μ§€ λͺ»ν•˜κ²Œ 될 수 μžˆλ‹€. κ·ΈλŸ¬λ―€λ‘œ 벽을 λΆ€μˆ˜μ§€ μ•Šκ³  λ°©λ¬Έν•  λ•Œμ˜ κ°€λŠ₯성도 μ—΄μ–΄μ•Ό ν•œλ‹€. λ”°λΌμ„œ ν•œ 칸에 λŒ€ν•΄ 벽을 λΆ€μˆ˜μ§€ μ•Šκ³  λ°©λ¬Έν–ˆμ„ λ•Œμ™€ 벽을 λΆ€μˆ˜κ³  λ°©λ¬Έν•  λ•Œλ‘œ λ‚˜λˆ  방문체크λ₯Ό ν•΄μ€˜μ•Ό ν•œλ‹€.

 

 

  •  λ°©λ¬Έμ²΄ν¬ : boolean[N][M][2]
    • [x][y][0] : 벽을 λΆ€μˆ˜μ§€ μ•Šκ³ , ν•΄λ‹Ή 지점을 λ°©λ¬Έν–ˆλŠ”κ°€
    • [x][y][1] : 벽을 λΆ€μˆ˜κ³ , ν•΄λ‹Ή 지점을 λ°©λ¬Έν–ˆλŠ”κ°€

 

 

 

 

 

μ½”λ“œ

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

public class Main {
	static int N, M;
	static int[][] graph;
	static boolean[][][] visited;
	static int[] dx = {-1, 1, 0, 0};
	static int[] dy = {0, 0, -1, 1};
	
	static class Point {
		int x;
		int y;
		int count;
		boolean hit;
		
		public Point(int x, int y, int count, boolean hit) {
			this.x = x;
			this.y = y;
			this.count = count;
			this.hit = hit;
		}
	}
	
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		StringTokenizer st = new StringTokenizer(br.readLine(), " ");
		N = Integer.parseInt(st.nextToken());
		M = Integer.parseInt(st.nextToken());
		
		graph = new int[N + 1][M + 1];
		visited = new boolean[N + 1][M + 1][2]; //0 : λ²½ μ•ˆλΆ€μˆ¨, 1: λ²½ λΆ€μˆ¨
		
		for(int i = 1; i <= N; i++) {
			String row = br.readLine();
			
			for(int j = 1; j <= M; j++) {
				graph[i][j] = row.charAt(j - 1) - '0';
			}
		}
		
		int answer = bfs(1, 1);
		
		System.out.println(answer);
	}
	
	public static int bfs(int i, int j) {
		Queue<Point> queue = new LinkedList<>();
		
		queue.add(new Point(i, j, 1, false));
		visited[i][j][0] = true;
		
		while(!queue.isEmpty()) {
			Point point = queue.poll();
			
			if(point.x == N && point.y == M) { // μ’…λ£Œ 쑰건
				return point.count;
			}
			
			for(int d = 0; d < 4; d++) {
				int nx = point.x + dx[d];
				int ny = point.y + dy[d];
				
				if(1 <= nx && nx <= N && 1 <= ny && ny <= M) {
					if(graph[nx][ny] == 0) { //λ²½ μ•„λ‹˜
						if(!point.hit && !visited[nx][ny][0]) { //λΆ€μˆœμ  μ—†μŒ
							queue.add(new Point(nx, ny, point.count + 1, false));
							visited[nx][ny][0] = true;
						} else if(point.hit && !visited[nx][ny][1]) { //λΆ€μˆœμ  있음
							queue.add(new Point(nx, ny, point.count + 1, true));
							visited[nx][ny][1] = true;
						}
					}else if(graph[nx][ny] == 1 && !point.hit) { //λ²½ 있음, λΆ€μˆœμ  μ—†μŒ
						queue.add(new Point(nx, ny, point.count + 1, true)); //λ²½ λΆ€μˆ˜κΈ°
						visited[nx][ny][1] = true;
					}
				}
			}
		}
		
		return -1;
	}

}

 

 

 

 

 

κ²°κ³Ό

 

 

 

 

 

배운점

  • 방문체크λ₯Ό ν•  λ•Œ, 벽을 λΆ€μ‰ˆλŠ”μ§€ μ•ˆλΆ€μ‰ˆλŠ”μ§€ λ‚˜λˆ μ„œ ν•΄μ•Ό ν•œλ‹€.
giraffe_