이번에 풀어본 문제는
백준 14890번 경사로 입니다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Main {
static int N,L,answer;
static int [][] map;
static boolean [][] isVis;
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());
map = new int[N][N];
for(int i = 0; i < N; ++i)
{
st = new StringTokenizer(br.readLine());
for(int j = 0; j < N; ++j)
{
map[i][j] = Integer.parseInt(st.nextToken());
}
}
isVis = new boolean[N][N];
for(int i = 0; i < N; ++i)
{
horizon(i,map[i][0]);
}
isVis = new boolean[N][N];
for(int i = 0; i < N; ++i)
{
vertical(i,map[0][i]);
}
System.out.print(answer);
}
static void horizon(int n, int h)
{
int j = 0;
int cur = h;
while(true)
{
if(j == N-1)
{
answer++;
break;
}
if(map[n][j+1] == cur) j++; // 다음칸과 동일
else if(Math.abs(map[n][j+1] - cur) >= 2) break; // 높이 2이상 차이
else // 높이 1차이
{
int next_h = map[n][j+1];
if(cur > next_h) // down
{
if(j+L >= N) break;
int startPoint = j+1;
for(int idx = startPoint; idx < startPoint+L; ++idx)
{
if(map[n][idx] != next_h || isVis[n][idx]) return;
isVis[n][idx] = true;
}
j += L;
cur--;
}
else // up
{
if(j-L+1 < 0) break;
for(int idx = j; idx > j-L; --idx)
{
if(map[n][idx] != cur || isVis[n][idx]) return;
isVis[n][idx] = true;
}
j++;
cur++;
}
}
}
}
static void vertical(int n, int h)
{
int i = 0;
int cur = h;
while(true)
{
if(i == N-1)
{
answer++;
break;
}
if(map[i+1][n] == cur) i++; // 다음칸과 동일
else if(Math.abs(map[i+1][n] - cur) >= 2) break; // 높이 2이상 차이
else // 높이 1차이
{
int next_h = map[i+1][n];
if(cur > next_h) // down
{
if(i+L >= N) break;
int startPoint = i+1;
for(int idx = startPoint; idx < startPoint+L; ++idx)
{
if(map[idx][n] != next_h || isVis[idx][n]) return;
isVis[idx][n] = true;
}
i += L;
cur--;
}
else // up
{
if(i-L+1 < 0) break;
for(int idx = i; idx > i-L; --idx)
{
if(map[idx][n] != cur || isVis[idx][n]) return;
isVis[idx][n] = true;
}
i++;
cur++;
}
}
}
}
}
구현 문제입니다.
각 끝점을 시작으로 가로, 세로 한번씩 탐색하도록 구성해 보았습니다.
현재 위치의 높이값을 계속 갱신하여 높이가 같을경우 다음인덱스로, 높이가 서로 다를경우 내리막인지, 오르막인지를 확인하여 경사로를 세우게 됩니다. 범위를 벗어났을 시 즉시 반복문을 벗어나고, 경사로를 세울 조건에 맞는다면 경사로를 세운 뒤 방문배열에 표시해줍니다. 겹치는 경사로가 없어야 하기 때문입니다. 앞선 방식으로 모든 경우의 수를 탐색해주면 결과의 갯수를 구할 수 있습니다.
오르막과 내리막을 구분하는 것 이외에는 딱히 복잡하지 않았던 것 같습니다.
개인적으로 구현문제를 좋아해서 아주 재밌게 풀었습니다 ㅎㅎ
제출해서 한방에 해결하면 기분이 참 좋은 것 같아요!