알고리즘 관련/BOJ

14890 경사로

Andrew-Yun 2021. 3. 11. 13:45

www.acmicpc.net/problem/14890

 

14890번: 경사로

첫째 줄에 N (2 ≤ N ≤ 100)과 L (1 ≤ L ≤ N)이 주어진다. 둘째 줄부터 N개의 줄에 지도가 주어진다. 각 칸의 높이는 10보다 작거나 같은 자연수이다.

www.acmicpc.net

단순한 구현 문제이지만, 확인해야할 조건들이 까다로운 문제이다.

조건 중에 특히 유의해야 할건 높이가 다른 칸인데, 다음 칸의 높이가 현재 칸보다 높은지 낮은지를 잘 구분해주어야 한다.

그렇지 않으면 확인하는 방향 기준 순방향, 역방향을 정할 수 없기 때문이다.

 

유의해야할 사항들은 다음과 같다.

1. 범위를 벗어나는 경사로를 설치하는 경우

2. 높이 차이가 1을 넘어가는 경사로를 설치하는 경우

3. 이미 설치한 경사로의 칸을 침범하여 경사로를 설치하는 경우

정답코드

#include <iostream>
using namespace std;
/*
1. 경사로를 이미 놓았는지 확인
2. 경사로를 놓을 수 있는 길이, 높이인지 확인
3. 경사로를 놓은 후 높이를 갱신한다.
*/
#define MAX_SIZE 100
#define FORWARD		0
#define BACKWARD	1
#define WIDTH		0
#define HEIGHT		1
int N, L;
int arr[MAX_SIZE][MAX_SIZE];
bool visit[MAX_SIZE][MAX_SIZE][2];
bool IsMakeLoad(int row, int col, int flag, int dir, int h)
{
	int nh = dir == 1 ? h : h - 1;
	if (flag == WIDTH) {
		//가로
		if (dir == FORWARD) {
			//순방향
			for (int i = 0; i < L; i++) {
				if (col + i >= N)
					return false;
				if (nh != arr[row][col + i])
					return false;
			}
		}
		else {
			//역방향
			if (col - L < 0)
				return false;
			for (int i = 1; i <= L; i++) {
				if (nh != arr[row][col - i])
					return false;
				if (visit[row][col - i][flag] == true)
					return false;
			}
		}
	}
	else {
		//세로
		if (dir == FORWARD) {

			for (int i = 0; i < L; i++) {
				if (row + i >= N)
					return false;
				if (nh != arr[row + i][col])
					return false;
			}
		}
		else {
			if (row - L < 0)
				return false;
			for (int i = 1; i <= L; i++) {
				if (nh != arr[row - i][col])
					return false;
				if (visit[row - i][col][flag] == true)
					return false;
			}
		}
	}
	return true;
}
int check(int row, int col, int flag)
{
	int h = arr[row][col];
	int dir;
	if (flag == WIDTH) {
		//세로
		while (col < N) {
			dir = h < arr[row][col];
			if (h != arr[row][col]) {
				if (abs(h - arr[row][col]) != 1)
					return false;
				if (IsMakeLoad(row, col, flag, dir, h)) {
					if (dir == FORWARD) {
						for (int k = 0; k < L; k++)
							visit[row][col + k][flag] = true;
					}
					else {
						for (int k = 1; k <= L; k++)
							visit[row][col - k][flag] = true;
					}
					h = arr[row][col];
				}
				else
					return false;
			}
			col++;
		}
	}
	else {
		while (row < N) {
			dir = h < arr[row][col];
			if (h != arr[row][col]) {
				if (abs(h - arr[row][col]) != 1)
					return false;
				if (IsMakeLoad(row, col, flag, h < arr[row][col], h)) {
					if (dir == FORWARD) {
						for (int k = 0; k < L; k++)
							visit[row + k][col][flag] = true;
					}
					else {
						for (int k = 1; k <= L; k++)
							visit[row - k][col][flag] = true;
					}
					h = arr[row][col];
				}
				else
					return false;
			}
			row++;
		}
	}
	return 1;
}
int main()
{
	int answer = 0;
	cin >> N >> L;
	for (int i = 0; i < N; i++)
		for (int j = 0; j < N; j++)
			scanf("%d", &arr[i][j]);
	for (int i = 0; i < N; i++)
		answer += check(0, i, HEIGHT);
	for (int i = 0; i < N; i++)
		answer += check(i, 0, WIDTH);
	printf("%d\n", answer);
	return 0;
}