백준 #1981 #Java
https://www.acmicpc.net/problem/1981
우선 이 문제가 이분탐색 문제인걸 인지하는 것이 먼저다.
bfs로 도착지점까지 가는 모든 경우의수를 체크하고, 경로마다 최대-최소의 값을 구하면 메모리초과가 날 것이다.
오른쪽 또는 아래로만 이동 가능하다고 하더라도 n이 100보다 작거나 같고 경우의 수만해도 대충 2^51는 되기 때문이다.
그럼 이동할 때 조건을 주며 이동을 해야될테고 경로의 최대, 최소값을 업데이트하면서 그 차이가 x이상 안나는 조건으로 이동하면 된다.
여기서 x를 선정해야되는데 이 작업을 이분탐색으로 해주면 된다.
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.*;
public class Main {
static int n;
static int[][] board;
static int[] dr = {0, 1, 0, -1};
static int[] dc = {1, 0, -1, 0};
public static void main(String[] args) throws Exception{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
n = Integer.parseInt(br.readLine());
board = new int[n][n];
StringTokenizer st;
int min = 200, max = 0;
for (int i=0; i<n; i++) {
st = new StringTokenizer(br.readLine());
for (int j=0; j<n; j++) {
int num = Integer.parseInt(st.nextToken());
board[i][j] = num;
min = num < min ? num : min;
max = num > max ? num : max;
}
}
int l = 0, r = max-min;
int ans = 0;
loop1 : while (l <= r) {
int gap = (l + r) / 2;
for (int i = min; i+gap <= max; i++) {
if (hasRoute(i, i+gap)) {
r = gap - 1;
ans = gap;
continue loop1;
}
}
l = gap + 1;
}
System.out.print(ans);
}
static boolean hasRoute(int min, int max) {
if (min > board[0][0] || board[0][0] > max) return false;
boolean[][] visit = new boolean[n][n];
Queue<int[]> que = new LinkedList<>();
que.add(new int[] {0, 0});
visit[0][0] = true;
while (!que.isEmpty()) {
int[] now = que.poll();
if (now[0] == n-1 && now[1] == n-1) return true;
for (int i=0; i<4; i++) {
int nr = now[0] + dr[i], nc = now[1] + dc[i];
if (0 <= nr && nr < n && 0 <= nc && nc < n && !visit[nr][nc]) {
if (min <= board[nr][nc] && board[nr][nc] <= max) {
visit[nr][nc] = true;
que.add(new int[] {nr, nc});
}
}
}
}
return false;
}
}
Author And Source
이 문제에 관하여(백준 #1981 #Java), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@mhi0118/백준-1981-Java저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)