SWEA 1861 - 정사각형 방

Updated:

Java

1861 번 - 정사각형 방

문제

N^2개의 방이 N×N형태로 늘어서 있다.

위에서 i번째 줄의 왼쪽에서 j번째 방에는 1이상 N2 이하의 수 Ai,j가 적혀 있으며, 이 숫자는 모든 방에 대해 서로 다르다.

당신이 어떤 방에 있다면, 상하좌우에 있는 다른 방으로 이동할 수 있다.

물론 이동하려는 방이 존재해야 하고, 이동하려는 방에 적힌 숫자가 현재 방에 적힌 숫자보다 정확히 1 더 커야 한다.

처음 어떤 수가 적힌 방에서 있어야 가장 많은 개수의 방을 이동할 수 있는지 구하는 프로그램을 작성하라.

접근 방법

전형적인 DFS와 BFS 응용 문제이다. 두 알고리즘을 공부하기 위해 각각 구현하여 사용해 보았다.
(0,0)에서 부터 시작하여 (n-1, n-1)까지 시작점을 각각 DFS와 BFS에 인자로 주며 호출한다.
DFS와 BFS가 끝나면 각 시작점에서 출발하여 얻은 결과 값들이 있으며, 이 결과 값이 기존 결과 값보다 더 크면, 갱신한다.
문제 조건에서 결과 값이 같으면, 시작 방 중 제일 작은 값을 출력하라 하였으므로
결과 값이 같다면 시작 방 값을 비교하여 더 작은 값으로 갱신한다.

구현

DFS와 BFS를 각각 구현하여 두개의 실행 결과 값을 비교한다.

코드

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

class Solution {
	static int arr[][], n;
	static int result = 0;
	static int smallest = 999999999;
	public static void main(String []args) throws Exception {  
		System.setIn(new FileInputStream("res/input.txt"));	//제출 할 때 주석해야함
    	BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    	StringTokenizer st;
    	int tc = stoi(br.readLine());
    	
    	for(int idx = 1; idx <= tc; idx++) {
    		n = stoi(br.readLine());
    		arr = new int[n][n];
    		int big = 0;
    		int startRoom = 0;
    		smallest = 999999999;
    		for(int i = 0; i < n; i++) {
    			st = new StringTokenizer(br.readLine());
    			for(int j = 0; j < n; j++) {
    				arr[i][j] = stoi(st.nextToken());
    			}
    		}
    		
    		for(int i = 0; i < n; i++) {			// 시작점 부여
    			for(int j = 0; j < n; j++) {
    				result = 0;
    				DFS(i,j, arr[i][j] - 1, 0);		// DFS로 해결, 둘 중 하나의 알고리즘으로 풀어본다.
    				//BFS(i,j);						// BFS로 해결
    				if(big < result) {				// DFS/ BFS의 결과 크기 비교
    					startRoom = arr[i][j];
    					big = result;
    				}
    				else if(big == result && arr[i][j] < startRoom) {		// 같은 결과면 방 값이 더 작은 값으로 갱신
    					startRoom = arr[i][j];
    				}
    			}
    		}
    		System.out.println("#" + idx + " " + startRoom +  " " + big);
    	}
	}
	
	static void DFS(int y, int x, int lastN, int cnt) {
		// 만약 범위를 벗어나거나, 현재 위치가 1차이가 나지 않으면 갈 수 없으므로 바로 종료
		if(y < 0 || y >= n || x < 0 || x >= n || arr[y][x] != lastN + 1) {
			result = Math.max(result, cnt);
			return;
		}
		DFS(y - 1, x, arr[y][x], cnt + 1);		//상
		DFS(y + 1, x, arr[y][x], cnt + 1);		//하
		DFS(y, x - 1, arr[y][x], cnt + 1);		//좌
		DFS(y, x + 1, arr[y][x], cnt + 1);		//우
	}
	
	//상, 우, 좌, 하
	static int goy[] = { 0, 1, -1, 0 };
	static int gox[] = { -1, 0, 0, 1 };
	static void BFS(int y, int x) {
		Queue<int[]> q = new LinkedList<int[]>();
		q.offer(new int[] {y,x});				// 시작점을 일단 queue에 넣는다.
		result++;
		int dy, dx, ty, tx;
		while(!q.isEmpty()) {					// queue가 비면 더 이상 이동하지 않으므로 종료
			int[] temp = q.poll();
			dy = temp[0];
			dx = temp[1];
			for(int i = 0; i < 4; i++) {		// 상하좌우 하나씩 방문한다.
				ty = dy + goy[i];				
				tx = dx + gox[i];
				// 만약 범위를 벗어나지 않고, 상하좌우 값 중 하나가 1의 차이어서 갈 수 있으면
				if(ty >= 0 && ty < n && tx >= 0 && tx < n && arr[ty][tx] == arr[dy][dx] + 1) {
					result++;					// 한칸 이동했으므로 증가
					q.offer(new int[] {ty,tx});	// 움직인 곳에서 다시 상하좌우를 방문하기 위해 queue에 넣는다.
				}
			}
		}
	}	
	static int stoi(String str) {
    	return Integer.parseInt(str);
    }
}

총평

난이도

⭐⭐⭐★★

후기

DFS와 BFS를 복습하는 문제 였다.

개선할 점