Post

(백준) 14890번 - 경사로

(백준) 14890번 - 경사로

(백준) 14890번 - 경사로

문제

https://www.acmicpc.net/problem/14890

풀이

배열을 행, 열 방향으로 순회하며 경사로를 설치한다.

지난 평지의 개수를 cnt에 저장했고, 내리막 경사로 설치 여부를 저장하는 down 변수를 사용했다.

  • 다음 길의 높이가 같으면 cnt를 증가시킨다.
  • 다음 길의 높이가 1만큼 큰 경우 cnt가 경사로 길이보다 작으면 설치할 수 없다.
  • 다음 길의 높이가 1만큼 낮은 경우 이전 내리막 경사로를 설치하지 못한 경우 현재 내리막 경사로 또한 설치할 수 없다.
  • 다음 길과의 높이 차가 2 이상이면 경사로를 설치할 수 없다.
  • 내리막 경사로를 설치하고 cnt, down 변수를 적절하게 초기화해야 한다.
  • 순회를 마쳤으나 내리막 경사로를 설치하지 못한 경우 불가능한 경우이다.

코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#include <iostream>

using namespace std;

int board[101][101];

int main() {
	int n, l;
	cin >> n >> l;

	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			cin >> board[i][j];
		}
	}

	int ans = 0;

	// 행 확인
	for (int i = 0; i < n; i++) {
		int cnt = 1; // 높이가 같은 길의 수
		bool down = false; // 내리막 경사로 설치해야하는지
		bool failed = false;
		for (int j = 0; j < n - 1; j++) {
			// 내리막 경사로 설치 후 초기화
			if (down && cnt >= l) {
				cnt = 0;
				down = false;
			}

			if (board[i][j] == board[i][j + 1]) {
				cnt++;
			}
			// 다음 길이 높은 경우
			else if (board[i][j] - board[i][j + 1] == -1) {
				if (cnt < l) {
					failed = true;
					break;
				}
				down = false;
				cnt = 1;
			}
			// 다음 길이 낮은 경우
			else if (board[i][j] - board[i][j + 1] == 1) {
				if (down) {
					failed = true;
					break;
				}
				down = true;
				cnt = 1;
			}
			// 높이 차가 2 이상
			else {
				failed = true;
				break;
			}
		}

		if (down && cnt < l) {
			failed = true;
		}
		if (!failed) ans++;
	}

	// 열 확인
	for (int j = 0; j < n; j++) {
		int cnt = 1; // 높이가 같은 길의 수
		bool down = false; // 높이가 낮아졌는가
		bool failed = false;
		for (int i = 0; i < n - 1; i++) {
			if (down && cnt >= l) {
				cnt = 0;
				down = false;
			}

			if (board[i][j] == board[i + 1][j]) {
				cnt++;
			}
			else if (board[i][j] - board[i + 1][j] == -1) {
				if (cnt < l) {
					failed = true;
					break;
				}
				down = false;
				cnt = 1;
			}
			else if (board[i][j] - board[i + 1][j] == 1) {
				if (down) {
					failed = true;
					break;
				}
				down = true;
				cnt = 1;
			}
			else {
				failed = true;
				break;
			}
		}

		if (down && cnt < l) {
			failed = true;
		}
		if (!failed) ans++;
	}

	cout << ans;
}

시간복잡도

이중 for문을 돌고 있으므로 $O(N^2)$이다.

공간복잡도

board 배열에서 $O(N^2)$이다.

This post is licensed under CC BY 4.0 by the author.