Algorithm/λ°±μ€€

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

giraffe_ 2023. 8. 30. 14:59

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

 

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

첫째 쀄에 N(1 ≤ N ≤ 1,000), M(1 ≤ M ≤ 1,000), K(1 ≤ K ≤ 10)이 μ£Όμ–΄μ§„λ‹€. λ‹€μŒ N개의 쀄에 M개의 숫자둜 맡이 μ£Όμ–΄μ§„λ‹€. (1, 1)κ³Ό (N, M)은 항상 0이라고 κ°€μ •ν•˜μž.

www.acmicpc.net

 

 

 

 

 

문제

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

 

 

 

 

 

풀이

λ²½ λΆ€μˆ˜κ³  μ΄λ™ν•˜κΈ° μ‹œλ¦¬μ¦ˆμ˜ λ¬Έμ œμ΄λ‹€. 1μ—μ„œλŠ” 벽을 ν•œ 개 κΉŒμ§€ λΆ€μˆ˜κ³  μ΄λ™ν–ˆμ§€λ§Œ, 이 λ¬Έμ œμ—μ„œλŠ” Kκ°œκΉŒμ§€ λΆ€μˆ˜κ³  μ΄λ™ν•œλ‹€.

 

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

 

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

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

www.acmicpc.net

 

 

 

κ·Έλž˜μ„œ λ²½ λΆ€μˆ˜κ³  μ΄λ™ν•˜κΈ°μ˜ 문제 풀이와 μœ μ‚¬ν•˜λ‹€.

https://programmingiraffe.tistory.com/145

 

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

https://www.acmicpc.net/problem/2206 2206번: λ²½ λΆ€μˆ˜κ³  μ΄λ™ν•˜κΈ° N×M의 ν–‰λ ¬λ‘œ ν‘œν˜„λ˜λŠ” 맡이 μžˆλ‹€. λ§΅μ—μ„œ 0은 이동할 수 μžˆλŠ” 곳을 λ‚˜νƒ€λ‚΄κ³ , 1은 이동할 수 μ—†λŠ” 벽이 μžˆλŠ” 곳을 λ‚˜νƒ€λ‚Έλ‹€. 당신은 (1, 1)에

programmingiraffe.tistory.com

 

 

 

 

 

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

 

 

 

1. 벽을 μ§€κΈˆκΉŒμ§€ λͺ‡ 개 λΆ€μ‰ˆλŠ”μ§€ 정보 μ €μž₯

 

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

 

 

 

2. 방문체크 : boolean[K][N][M]

 

 λ°©λ¬Έμ²΄ν¬λ₯Ό ν•  λ•Œ, ν—€λ‹Ή 지점에 λŒ€ν•΄ μ§€κΈˆκΉŒμ§€ 벽을 λͺ‡ 번 λΆ€μˆ˜κ³  λ°©λ¬Έν–ˆλŠ”κ°€ μ•ˆν–ˆλŠ”κ°€λ₯Ό ν‘œμ‹œν–ˆλ‹€. ν•΄λ‹Ή 지점에 ν•œλ²ˆλ„ μ•ˆλΆ€μˆ˜κ³  λ°©λ¬Έν•  μˆ˜λ„ 있고, 1번 λΆ€μˆ˜κ³  λ°©λ¬Έν•  μˆ˜λ„ 있고, .. K번 λΆ€μˆ˜κ³  λ°©λ¬Έν•  μˆ˜λ„ 있기 λ•Œλ¬Έμ΄λ‹€. 그리고 λ¨Όμ € n번 λΆ€μˆ˜κ³  λ°©λ¬Έν–ˆμ–΄λ„ 후에 κ·Έ κ²½λ‘œκ°€ 더이상 탐색이 λΆˆκ°€λŠ₯ν•œ κ²½λ‘œκ°€ 될 μˆ˜λ„ μžˆλ‹€.

 

 

* λ°±μ€€μ˜ 문제 λ‚΄ κ²Œμ‹œνŒμ—μ„œ 본건데, λ°°μ—΄μ˜ 차원 μ„ μ–Έ μˆœμ„œκ°€ λ©”λͺ¨λ¦¬μ™€ μˆ˜ν–‰μ‹œκ°„μ— 영ν–₯을 λ―ΈμΉœλ‹€κ³  ν•œλ‹€. 

(https://www.acmicpc.net/board/view/111938)

 

visited[11][1000][1000]κ°€ visited[1000][1000][11] 보닀 λ©”λͺ¨λ¦¬ μ‚¬μš©λŸ‰μ΄ 훨씬 적닀. 채점을 λŒλ Έμ„ λ•Œλ„ 500ms 정도 차이가 났닀.

 

 

 

3. 벽인지 벽이 μ•„λ‹Œμ§€μ— 따라 탐색을 λ‹€λ₯΄κ²Œ ν–ˆλ‹€.

 

  • 벽이 μ•„λ‹ˆλ‹€
    • μ§€κΈˆκΉŒμ§€ n개 λΆ€μˆ΄ λ°©λ¬Έν•œμ μ΄ μ—†μŒ => n개 κ·ΈλŒ€λ‘œ 탐색
  • 벽이닀
    • μ§€κΈˆκΉŒμ§€ K개 미만 λΆ€μˆ¨
    • μ§€κΈˆκΉŒμ§€ n +1개 λΆ€μˆ΄ λ°©λ¬Έν•œμ μ΄ μ—†μŒ=> n+1 λΆ€μˆ˜κ³  탐색

 

 

 

 

 

μ½”λ“œ

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

public class Main {
	static int N, M, K;
	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;
		int hit;
		
		public Point(int x, int y, int count, int 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());
		K = Integer.parseInt(st.nextToken());
		
		graph = new int[N + 1][M + 1];
		visited = new boolean[K + 1][N + 1][M + 1]; //0 : λ²½ μ•ˆλΆ€μˆ¨, 1~K: λ²½ n개 λΆ€μˆ¨
		
		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, 0));
		visited[0][i][j] = 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 && !visited[point.hit][nx][ny]) { //λ²½ μ•„λ‹˜
						queue.add(new Point(nx, ny, point.count + 1, point.hit));
						visited[point.hit][nx][ny] = true;
					}else if(graph[nx][ny] == 1 && point.hit < K && !visited[point.hit + 1][nx][ny]) { //λ²½ 있음, k개 미만 λΆ€μˆ¨, n+1λΆ€μˆ˜κ³  λ°©λ¬Έν•œμ  μ—†μŒ
						queue.add(new Point(nx, ny, point.count + 1, point.hit + 1)); //λ²½ λΆ€μˆ˜κΈ°
						visited[point.hit + 1][nx][ny] = true;
					}
				}
			}
		}
		
		return -1;
	}

}

 

 

 

 

 

κ²°κ³Ό

 

1480ms κ±Έλ¦¬λŠ” κ²°κ³Ό : visited[11][1000][1000]

1992ms κ±Έλ¦¬λŠ” κ²°κ³Ό : visited[1000][1000][11]

 

 

 

 

 

배운점

  • 3차원 방문체크
    • visited[11][1000][1000] κ°€ visited[1000][1000][11] 보닀 μ‹œκ°„μ΄ 적게 λ“ λ‹€