알고리즘문제풀이

[JAVA] SWEA 4014 활주로 건설

Hindsight.. 2020. 8. 20. 08:57

전체 코드

import java.util.Scanner;

public class SWEA_4014_활주로건설 {

	static int N, T, X, CNT;

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		T = sc.nextInt();

		for (int test = 1; test <= T; test++) {
			CNT = 0;
			N = sc.nextInt();
			X = sc.nextInt();

			int arr[][] = new int[N][N];

			for (int i = 0; i < N; i++) {
				for (int j = 0; j < N; j++) {
					arr[i][j] = sc.nextInt();
				}
			}

			for (int i = 0; i < N; i++) {
				chk(arr[i]);
			}

			for (int i = 0; i < N; i++) {
				int tmp[] = new int[N];
				for (int j = 0; j < N; j++) {
					tmp[j] = arr[j][i];
				}
				chk(tmp);
			}
			
			System.out.println("#"+test+ " " + CNT);

		}
	}

	private static void chk(int[] arr) {
		// check
		int f = arr[0];
		boolean chk = false;
		
		for (int i = 0; i < N; i++) { // 모두 같은 수인지 체크, 모두 같으면 가능하므로 빨리끝내기 위함
			if (f != arr[i]) {
				chk = true;
				break;
			}
		}
		
		if(!chk) {
			CNT++;
			return;
		}

		int cnt = 0;
		int now;
		for (int i = 0; i < N; i++) {
			now = arr[i];
			if (now == f)
				cnt++;
			else {
				if(now == f+1) { //높아질 때, 지나온 길에 설치하는 것이므로 인덱스 변화 x
					if(cnt>=X){//건설가능
						cnt = 1;
					}else// 건설불가
						return;
					
				}else if(now == f-1) { //낮아질때, 앞에 설치할 수 있는지 체크해야 하므로 인덱스 추가
					if(i + X - 1 < N) { //건설가능, 앞에 길 있는지 체크
						for(int j = i; j<i+X; j++) {
							if(arr[j] != now)
								return;
						}
						cnt  = 0;
						i = i + X-1;
					}else
						return;
				}else
					return;
				
				f = now;
			}
			
		}
		CNT++;
	}

}

 

문제 핵심 코드

 

private static void chk(int[] arr) {
	// check
	int f = arr[0];
	boolean chk = false;
	
	for (int i = 0; i < N; i++) { // 모두 같은 수인지 체크, 모두 같으면 가능하므로 빨리끝내기 위함
		if (f != arr[i]) {
			chk = true;
			break;
		}
	}
	
	if(!chk) {
		CNT++;
		return;
	}

	int cnt = 0;
	int now;
	for (int i = 0; i < N; i++) {
		now = arr[i];
		if (now == f)
			cnt++;
		else {
			if(now == f+1) { //높아질 때, 지나온 길에 설치하는 것이므로 인덱스 변화 x
				if(cnt>=X){//건설가능
					cnt = 1;
				}else// 건설불가
					return;
				
			}else if(now == f-1) { //낮아질때, 앞에 설치할 수 있는지 체크해야 하므로 인덱스 추가
				if(i + X - 1 < N) { //건설가능, 앞에 길 있는지 체크
					for(int j = i; j<i+X; j++) {
						if(arr[j] != now)
							return;
					}
					cnt  = 0;
					i = i + X-1;
				}else
					return;
			}else
				return;
			
			f = now;
		}
		
	}
	CNT++;
}

 

chk함수에 배열만 넣으면 해당 열 또는 행을 체크할 수 있도록 설계 했다.

 

높이가 높아질 때낮아질 때 두가지 경우를 나눠서 생각하면 쉬운 문제였다.

 

높아질 땐 지나온 경로이므로 그동안의 카운트가 X보다 크거나 같은지를 체크해 경사로를 설치할 수 있는지 체크하고,

 

낮아질 땐 현재 위치의 앞에 X칸 만큼의 높이가 현재 높이와 같은지 체크한다.

 

이 두가지 경우를 생각하는 것이 문제의 핵심이었다!