컴퓨터 사이언스/1고리즘

백준 14890 : 경사로

저세상 개발자 2021. 8. 16. 01:20

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

 

14890번: 경사로

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

www.acmicpc.net

 

단순 구현문제다. N의 범위가 매우 작으므로 부르트포스로 풀면 된다.

행과 열에 대하여 모두 검사해야하므로 동일한 로직의 거의 비슷한 코드가 두 번 반복된다.

나는 이 부분을 하나의 함수에서 포인터를 사용하여 해결했다.

 

처음에 작성한 로직은 메인 함수 바로 위에 참고용으로 넣어뒀는데, idx를 증가시키면서 배열을 순회하는 while문 안에서 동일한 작동을 하는 while문을 다시 호출함으로써 코드가 지저분해졌다.

로직이 한 눈에 들어오지도 않고 특히 flat값과 idx값을 정해주는데 있어서 시간을 들여 고민할 필요가 있다.

반면에 깔끔한 코드는 이러한 부분들을 고민할 필요 없이 한 번의 while문을 돌면서 로직 안에서 처리된다.

 

#include <iostream>

#define BREAK flag=0;break
using namespace std;

int n, L;
int board[100][100];

//가독성이 뛰어난 코드
bool check(int i, bool dir) {
	int idx, prev, cur, flat, tmp;
	int *x, *y;

	if (!dir) y = &i, x = &idx;
	else x = &i, y = &idx;

	idx = 0, flat = 1, prev = board[*y][*x];
	for (idx = 1; idx < n; idx++) {
		cur = board[*y][*x];
		if (cur == prev) ++flat;
		else if (prev == cur - 1 && flat >= L) flat = 1;
		else if (prev == cur + 1 && flat >= 0) flat = -L + 1;
		else break;
		prev = cur;
	}

	return (idx == n && flat >= 0);
}

int find_path() {
	int ret = 0;

	for (int i = 0; i < n; i++) {
		ret += check(i, 0);
		ret += check(i, 1);
	}

	return ret;
}

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

	cout << find_path();
}

//사용하지 않음
//처음에 사용한 코드, 지저분함 로직이 한 눈에 들어오지 않음
bool dirty_code_check(int i, bool dir) {
	int idx, prev, cur, flat, tmp;
	bool flag;

	int* x, * y;
	if (!dir) y = &i, x = &idx;
	else x = &i, y = &idx;

	idx = 0, prev = board[*y][*x], flat = 0, flag = 1;
	while (idx < n) {
		cur = board[*y][*x];
		if (cur == prev) ++flat;
		else if (prev == cur + 1 || prev == cur - 1) {
			if (prev < cur) {
				if (flat < L) { BREAK; }
				flat = 1;
			}
			else {
				//특히 이 부분에서 idx가 어떻게 변하는지, flat값을 어떻게 줘야하는지
				//고민할 시간이 필요함. 밑에 check함수가 훨씬 가독성면에서 뛰어남
				flat = 1;
				++idx;
				while (idx < n && flat < L && board[*y][*x] == cur) ++idx, ++flat;
				if (flat < L) { BREAK; }
				flat = 0;
				--idx;
			}
			prev = cur;
		}
		else { BREAK; }
		++idx;
	}

	return flag;
}

int main() {
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	solution();

	return 0;
}
메모리: 2060 kb 시간: 0 ms