baekjoon/Implementation
백준 14890번 : 경사로 [자바]
Meluu_
2025. 7. 23. 11:49
🧫 문제 분석
✔️ 출처
📖 문제

구현 문제
높이 차가 1인 각 칸의 연결을 어떻게 해결하는가가 관건
한쪽 방향이 아닌 양쪽에서 높이차를 두었을때 어떻게 해결할 것인가
단, 높이가 1을 초과한다면 지나갈 수 없다.
행은 행끼리
열은 열끼리 문제를 나눠 풀되 로직은 같다.
행을 기준으로
A행이라고 가정하고
A 행의 0열을 이전값으로 삶고
A행의 1열과 비교해서 같다면 같은 수를 센다.
현재보다 높이가 높은 다음 칸을 만날경우
여태 센 같은 수의 개수가 경사로의 설치 기준 개수를 넘어선다면
높이가 높은 칸을 자연스럽게 지나가면 된다.
반대로
현재보다 높이가 낮은 다음 칸을 만날 경우
다음칸부터 다음칸의 같은 높이를 가지는 연속된 칸들의 개수를 센다.
그 수가 경사로 설치 기준 개수를 넘어선다면
경사로를 설치하고 난 이후의 위치로 이동하면된다.
🔅 문제 풀이
import java.io.*;
import java.util.*;
public class Main {
// 14890번 경사로
static int n, l;
static int[][] arr;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
n = Integer.parseInt(st.nextToken());
l = Integer.parseInt(st.nextToken());
arr = new int[n][n];
for (int i = 0; i < n; i++) {
st = new StringTokenizer(br.readLine());
for (int j = 0; j < n; j++) {
arr[i][j] = Integer.parseInt(st.nextToken());
}
}
int answer = 0;
for (int i = 0; i < n; i++) {
if (checkColLine(arr[i][0], i)) answer++;
if (checkRowLine(arr[0][i], i)) answer++;
}
System.out.println(answer);
}
private static boolean checkColLine(int prev, int fixRow) {
int cnt = 1;
int col = 1;
while (col < n) {
// 높이 차가 1보다 크다면 불가능
if (Math.abs(prev - arr[fixRow][col]) > 1) return false;
// 이전 값이 현재 값보다 작다면
if (prev < arr[fixRow][col]) {
prev = arr[fixRow][col];
if (cnt >= l) cnt = 1;
else return false;
// 현재가 더 높다면
} else if (prev > arr[fixRow][col]) {
// 현재~ 현재 + l 까지 설치 가능한지 확인
int temp = arr[fixRow][col];
int tempCnt = 1;
for (int j = col + 1; j < n; j++) {
if (temp != arr[fixRow][j]) break;
tempCnt++;
}
// 설치가능이라면
if (tempCnt >= l) {
prev = arr[fixRow][col]; // 이전값은 현재 값으로
col += l; cnt = 0; //col + l 위치부터 시작하므로 col+l부터 탐색하게 0으로 초기화
continue;
}
// 설치 불가능이라면 이 행은 불가능
return false;
} else {
cnt++;
}
col++;
}
return true;
}
private static boolean checkRowLine(int prev, int fixCol) {
int cnt = 1;
int row = 1;
while (row < n) {
// 높이 차가 1보다 크다면 불가능
if (Math.abs(prev - arr[row][fixCol]) > 1) return false;
// 이전 값이 현재 값보다 작다면
if (prev < arr[row][fixCol]) {
prev = arr[row][fixCol];
// 설치가능하다면 설치하고 이동
if (cnt >= l) cnt = 1;
else return false;
// 현재가 더 높다면
} else if (prev > arr[row][fixCol]) {
// 현재~ 현재 + l 까지 설치 가능한지 확인
int temp = arr[row][fixCol];
int tempCnt = 1;
for (int j = row + 1; j < n; j++) {
if (temp != arr[j][fixCol]) break;
tempCnt++;
}
// 설치가능이라면
if (tempCnt >= l) {
prev = arr[row][fixCol]; // 이전값은 현재 값으로
row += l; cnt = 0;
continue;
}
// 설치 불가능이라면 이 행은 불가능
return false;
} else {
cnt++;
}
row++;
}
return true;
}
}
❗ 오답노트 / 필요한 지식
- 항상 인덱스를 확 넘어갈때는 뭔가를 세는 것이 정확한지, 인덱스를 넘기고 추가적으로 연산이 더 들어가는건 아닌지 잘 확인하자.