hotamul의 개발 이야기

[Algorithm][C++] SWEA. 4014. [모의 SW 역량테스트] 활주로 건설 본문

myt-algorithm-practice/Samsung SW Certi Adv

[Algorithm][C++] SWEA. 4014. [모의 SW 역량테스트] 활주로 건설

hotamul 2021. 11. 15. 21:59

url: https://swexpertacademy.com/main/code/problem/problemDetail.do?contestProbId=AWIeW7FakkUDFAVH 

 

SW Expert Academy

SW 프로그래밍 역량 강화에 도움이 되는 다양한 학습 컨텐츠를 확인하세요!

swexpertacademy.com

 

풀이 핵심

1. 높이 차이가 2 이상 나는지 확인해주기, 내리막길 + 오르막길 일 경우 경사로가 중복인지 확인하기

이 두가지만 잘 확인해준다면 쉽게 풀 수 있다.

 

2. 행/열을 각각 체크해주려면 경사로 중복 배열을 행 체크 후 다시 초기화시켜줘야 하므로 행 체크만 할 수 있도록 입력에서 처리해준다. (따라서 행을 2 * N번 체크해줘야 함)

...
scanf("%d", &map[r][c]);
map[N + c][r] = map[r][c];
...

 

3. line_pass, point_pass 두 가지 pass 조건을 확인하며 각 행을 체크한다.

- 높이가 다른 곳을 만나면 높이차이가 1인지 확인한다. 그렇지 않으면 line_pass를 false로 변경하고 행 체크를 종료한다.

 

- 높이차이가 1이라면 체크해야 하는 위치, 방향(오르막길, 내리막길)을 확인한다.

 

- 만약 오르막길이라면 체크해야하는 위치에 경사로가 놓여있는지 확인한다.

 

코드

#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#define MAXN	20

int T, N, X;
int map[2 * MAXN][MAXN];
bool check[2 * MAXN][MAXN];

int get_abs(int value) {
	return value > 0 ? value : -value;
}

int solve() {
	int ret = 0;
	for (int r = 0; r < 2 * N; r++) {
		bool line_pass = true;
		int cur = map[r][0];
		int c = 1;
		while (1) {
			if (c == N) {
				break;
			}
			if (cur != map[r][c]) {
				if (get_abs(cur - map[r][c]) != 1) {
					line_pass = false;
					break;
				}
				bool point_pass = false;
				int cnt = 1;
				int target, target_idx, dc;
				if (cur > map[r][c]) {
					target = map[r][c];
					target_idx = c + 1;
					dc = +1;
				}
				else {
					if (check[r][c - 1]) {
						line_pass = false;
						break;
					}
					target = cur;
					target_idx = c - 2;
					dc = -1;
				}
				while (1) {
					if (cnt == X) {
						point_pass = true;
						if (dc == 1) {
							cur = target;
							c = target_idx;
							check[r][target_idx - 1] = true;
						}
						else {
							cur = map[r][c];
							c++;
						}
						break;
					}
					if (target_idx < 0 || target_idx >= N || \
						target != map[r][target_idx] || check[r][target_idx]) {
						break;
					}
					cnt++;
					target_idx += dc;
				}
				if (!point_pass) {
					line_pass = false;
					break;
				}
			}
			else {
				c++;
			}
		}
		if (line_pass) {
			ret++;
		}
	}

	return ret;
}

int main() {
	// freopen("input.txt", "r", stdin);
	scanf("%d", &T);
	for (int tc = 1; tc <= T; tc++) {
		scanf("%d %d", &N, &X);
		for (int r = 0; r < N; r++) {
			for (int c = 0; c < N; c++) {
				scanf("%d", &map[r][c]);
				check[r][c] = check[N + c][r] = 0;
				map[N + c][r] = map[r][c];
			}
		}

		int ans = solve();
		printf("#%d %d\n", tc, ans);
	}
	return 0;
}

 

조건을 깔끔하게 만들지 못해 아쉽다. 남이 이해하기에는 조금 시간이 걸릴 좋지 않은 코드라고 생각한다.

Comments