담배팔이소년

[BOJ] 14442 벽 부수고 이동하기 2 본문

Algorithm

[BOJ] 14442 벽 부수고 이동하기 2

bkkmw 2023. 1. 18. 23:42

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

 

문제 풀이

 

package boj;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;

public class MainB_14442 {
	
	static int dir_yx[][] = new int[][] {
		{-1,0}, {0,+1}, {+1,0}, {0,-1}
	};

	public static void main(String[] args) throws Exception{
		System.setIn(new FileInputStream("input/boj/input_14442.txt"));
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st;
		
		st = new StringTokenizer(br.readLine(), " ");
		int N = Integer.parseInt(st.nextToken());
		int M = Integer.parseInt(st.nextToken());
		int K = Integer.parseInt(st.nextToken());
		
		int map[][] = new int[N][M];
		
		for(int i=0; i<N; i++) {
			String line = br.readLine();
			for(int j=0; j<M; j++)
				map[i][j] = line.charAt(j) - 48;
		}
		
		int ans = solve(map, N, M, K);
		
		System.out.println(ans);
		br.close();
	}
	
	static int solve(int[][] map, int N, int M, int K) {
        if(N==1 && M==1) return 1;
		int ret = Integer.MAX_VALUE;
		int visited[][][] = new int[N][M][K+1];
		Queue<int[]> q = new LinkedList<int[]>();
		
		fill_cube(visited, Integer.MAX_VALUE);
		fill_next(visited[0][0], 0, K+1, 1);
		// y pos, x pos, broken, dist
		q.add(new int[] {0, 0, 0, 1});

		while(!q.isEmpty()) {
			int cur[] = q.poll();
			
			if(cur[3]+1 >= ret) continue;
			
			for(int d=0; d<4; d++) {
				int ny = cur[0] + dir_yx[d][0];
				int nx = cur[1] + dir_yx[d][1];
				
				if(ny<0 || ny>N-1 || nx<0 || nx>M-1) continue;
				if(visited[ny][nx][cur[2]] <= cur[3] + 1) continue;
				
				if(ny == N-1 && nx == M-1) {
					if(visited[ny][nx][cur[2]] > cur[3] + 1) {
						visited[ny][nx][cur[2]] = cur[3] + 1;
						ret = find_min(visited[ny][nx], K+1);
					}
					continue;
				}
				
				if(map[ny][nx] == 0) {
					if(visited[ny][nx][cur[2]] <= cur[3] + 1) continue;
					else {
						fill_next(visited[ny][nx], cur[2], K+1, cur[3] + 1);
						q.add(new int[] {ny, nx, cur[2], cur[3] + 1});
					}
				}
				else {
					if(cur[2] >= K) continue;
					if(visited[ny][nx][cur[2]+1] <= cur[3] + 1) continue;
					fill_next(visited[ny][nx], cur[2]+1, K+1, cur[3] + 1);
					q.add(new int[] {ny, nx, cur[2] + 1, cur[3] + 1});
				}
			}
			
		}
		
		return (ret == Integer.MAX_VALUE) ? -1 : ret;
	}
	
	static void fill_next(int[] pos, int k, int K, int dist) {
		for(int i=k;i <K; i++) {
			if(pos[i] < dist) return;
			pos[i] = dist;
		}
	}
	
	static void fill_cube(int[][][] cube, int val) {
		int N = cube.length;
		int M = cube[0].length;
		int K = cube[0][0].length;
		
		for(int i=0; i<N; i++)
			for(int j=0; j<M; j++)
				for(int k=0; k<K; k++)
					cube[i][j][k] = val;
	}
	
	static int find_min(int counts[], int K) {
		int ret = Integer.MAX_VALUE;
		for(int i=0; i<K; i++) {
			if(counts[i] < ret) {
				ret = counts[i];
			}
		}
		return (ret == Integer.MAX_VALUE) ? -1 : ret;
	}
}

'Algorithm' 카테고리의 다른 글

[BOJ] 17825 주사위 윷놀이  (0) 2023.04.27
[Programmers] 140107 점 찍기  (0) 2023.04.16
[BOJ] 13415 정렬 게임  (0) 2023.01.18
[BOJ] 01446 지름길  (0) 2023.01.15
[BOJ] 17143 낚시왕  (0) 2023.01.07
Comments