[BOJ 1981] 배열에서 이동 (Java)

nnm·2020년 2월 27일
0

BOJ 1981 배열에서 이동

문제풀이

투포인터 + BFS 문제다. 투포인터는 두 변수가 변화하면서 상관관계를 만들어낼 때 사용하면 되는 것 같다? 또 모든 문제가 그렇듯이 주어진 문제를 단순화해야한다. 단순화의 가장 쉬운 방법이 변수를 고정하는 것이다.

  • 완전탐색으로 풀기에는 너무 많은 경우의 수가 발생하게 되기 때문에 경우를 한정지어야 한다.
  • 최댓값과 최솟값을 정해놓고 그 사이에서 탐색이 가능한지 확인한다.
  • 탐색 가능 여부를 통해 최솟값 ~ 최댓값의 범위를 조정한다.

구현코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;

public class Main {
	
	static class Node {
		int r, c;
		
		Node(int r, int c){
			this.r = r;
			this.c = c;
		}
	}
	
	static ArrayList<Integer> numbers;
	static int[][] map;
	static int N;
	
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = null;
		
		N = stoi(br.readLine());
		
		numbers = new ArrayList<>();
		map = new int[N][N];
		
		for(int r = 0 ; r < N ; ++r) {
			st = new StringTokenizer(br.readLine());
			for(int c = 0 ; c < N ; ++c) {
				map[r][c] = stoi(st.nextToken());
				if(!numbers.contains(map[r][c])) {
					numbers.add(map[r][c]);
				}
			}
		}
		Collections.sort(numbers);
		
		solve();
	}
	
	private static void solve() {
		int min = 0, max = 0;
		int ans = Integer.MAX_VALUE;
		
		while(min < numbers.size() && max < numbers.size()) {
			if(bfs(numbers.get(min), numbers.get(max))) {
				int gap = numbers.get(max) - numbers.get(min);
				ans = ans > gap ? gap : ans;
				min++;
			} else {
				max++;
			}
		}
		
		System.out.println(ans);
	}

	private static boolean bfs(int min, int max) {
		if(map[0][0] < min || map[0][0] > max) return false;
		
		int[][] dir = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
		boolean[][] visited = new boolean[N][N];
		Queue<Node> q = new LinkedList<>();
		
		q.offer(new Node(0, 0));
		visited[0][0] = true;
		
		while(!q.isEmpty()) {
			Node now = q.poll();
			
			if(now.r == N - 1 && now.c == N - 1) {
				return true;
			}
			
			for(int d = 0 ; d < 4 ; ++d) {
				int nr = now.r + dir[d][0];
				int nc = now.c + dir[d][1];
				
				if(nr >= N || nr < 0 || nc >= N || nc < 0 || visited[nr][nc]) continue;
				
				if(map[nr][nc] >= min && map[nr][nc] <= max) {
					visited[nr][nc] = true;
					q.offer(new Node(nr, nc));
				}
			}
		}
		return false;
	}

	private static int stoi(String s) {
		return Integer.parseInt(s);
	}
}
profile
그냥 개발자

0개의 댓글