SWEA 4014 - 활주로 건설
Updated:
Java
4014 번 - 활주로 건설
문제
경사로의 길이 X 와 절벽지대의 높이 정보가 주어질 때,
활주로를 건설할 수 있는 경우의 수를 계산하는 프로그램을 작성하라.
- N 의 크기는 6 이상 20 이하의 정수이다. ( 6 ≤ N ≤ 20 )
- 경사로의 높이는 항상 1 이고, 길이 X 는 2 이상 4 이하의 정수이다. ( 2 ≤ X ≤ 4 )
- 지형의 높이는 1 이상 6 이하의 정수이다.
- 동일한 셀에 두 개 이상의 경사로를 겹쳐서 사용할 수 없다.
접근 방법
행 단위로 탐색하는 경우와 열 단위로 탐색하는 경우를 나누어 생각을 해보았다.
각 행/열 마다 차례로 탐색하면서, 각 값과 이전 값을 비교한다.
비교하면 총 4가지의 경우가 있는데
- 이전 높이와 현재 높이가 같은 경우
- 현재 높이가 이전 높이보다 1 큰 경우
- 현재 높이가 이전 높이보다 1 작은 경우
- 높이 차이가 2 이상인 경우
1번의 경우 평평하므로, 현재까지 평평한 길이의 값을 갱신해준다.
2번의 경우 오르막 경사로를 설치하여야 하는데, 1번에서 체크한 평평한 길이의 값과 비교하여, 평평한 길이의 값이 크면 오르막 경사로를 설치 할 수 있다고 판단한다.
3번의 경우 현재부터, 경사로 길이까지 평평한지 확인한다.
4번의 경우 경사로를 설치 할 수 없으므로 실패한다.
코드
import java.io.*;
import java.util.*;
class Solution {
static int result = 0;
static int[][] map;
static int n , x;
static boolean[][] vis;
public static void main(String []args) throws Exception {
System.setIn(new FileInputStream("res/input.txt")); //제출 할 때 주석해야함
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer stk;
int tc = stoi(br.readLine());
for(int tidx = 1; tidx <= tc; tidx++) {
result = 0;
stk = new StringTokenizer(br.readLine());
n = stoi(stk.nextToken());
x = stoi(stk.nextToken());
map = new int[n][n];
for(int i = 0; i < n; i++) {
stk = new StringTokenizer(br.readLine());
for(int j = 0; j < n; j++) {
map[i][j] = stoi(stk.nextToken());
}
}
result = process();
System.out.println("#" + tidx + " " + result);
}
}
private static int process() {
int count = 0;
for(int i = 0; i < n; i++) {
if(makeRoadByRow(i))
count++;
if(makeRoadByCol(i))
count++;
}
return count;
}
private static boolean makeRoadByRow(int i) {
// 이전 높이, 현재까지 같은 높이의 길이, len : 오르막 경사를 설치 할 수 있는지의 여부를 확인
int lastH = map[i][0] , len = 0;
int j = 0; // 탐색 열 위치
while(j < n) {
if(lastH == map[i][j]) {
len++;
j++;
}
else if(lastH + 1 == map[i][j]) { // 오르막 경사로 설치 가능 판단
if(len < x) // 현재까지 같은 높이의 활주로 길이가 경사로보다 작은 경우
return false;
lastH++;
len = 1;
j++;
}
else if(lastH - 1 == map[i][j]) { // 내리막 경사로 설치 가능 판단
int count = 0; // 경사로의 길이
for(int k = j; k < n; k++) {
if(lastH - 1 != map[i][k]) { // 높이 차이가 1이 아닌 경우 반복문을 빠져나온다.
break;
}
if(++count == x) // 높이 차이가 1이면 경사로 길이를 증가하며, 길이가 경사로 길이 x갸 되면 종료한다.
break;
}
if(count < x) // 설치 할 수 있는 경사로 길이가 주어진 경사로 길이 x보다 짧으면 실패한다.
return false;
lastH--;
len = 0; // 현재 위치까지 경사로를 깔았으므로, 이전 위치에 경사로를 깔 수 없어 현재까지의 길이를 0으로 둔다.
j = j + x;
}
else
return false;
}
return true;
}
private static boolean makeRoadByCol(int i) {
// 이전 높이, 현재까지 같은 높이의 길이, len : 오르막 경사를 설치 할 수 있는지의 여부를 확인
int lastH = map[0][i] , len = 0;
int j = 0; // 탐색 열 위치
while(j < n) {
if(lastH == map[j][i]) {
len++;
j++;
}
else if(lastH + 1 == map[j][i]) { // 오르막 경사로 설치 가능 판단
if(len < x) // 현재까지 같은 높이의 활주로 길이가 경사로보다 작은 경우
return false;
lastH++;
len = 1;
j++;
}
else if(lastH - 1 == map[j][i]) { // 내리막 경사로 설치 가능 판단
int count = 0; // 경사로의 길이
for(int k = j; k < n; k++) {
if(lastH - 1 != map[k][i]) { // 높이 차이가 1이 아닌 경우 반복문을 빠져나온다.
break;
}
if(++count == x) // 높이 차이가 1이면 경사로 길이를 증가하며, 길이가 경사로 길이 x갸 되면 종료한다.
break;
}
if(count < x) // 설치 할 수 있는 경사로 길이가 주어진 경사로 길이 x보다 짧으면 실패한다.
return false;
lastH--;
len = 0; // 현재 위치까지 경사로를 깔았으므로, 이전 위치에 경사로를 깔 수 없어 현재까지의 길이를 0으로 둔다.
j = j + x;
}
else
return false;
}
return true;
}
// 주어진 범위 안에 있는가
public static boolean isIn(int y, int x){
if(y < 0 || y >= n || x < 0 || x >= n)
return false;
return true;
}
static int stoi(String str) {
return Integer.parseInt(str);
}
}
총평
후기
매우 더럽게 푼 문제
개선할 점
없