문제
https://www.acmicpc.net/problem/14890
풀이
배열이 나와서 완전탐색 문제인가 싶었지만 시뮬레이션 문제였다. 실수가 많아서 시간이 좀 걸렸다. 배열을 초기화하지 않아서 이상한 값이 들어가 틀리고, 배열에 들어갈 수 있는 범위를 체크해주지 않아서 런타임 에러가 뜨고, 경사로를 겹쳐도 되게 만들어서 틀리고... 항상 조건을 잘 파악하고, 알고리즘을 짤 때 내가 생각한대로 나오는지 꼼꼼히 체크하도록 하자. 기본적인 아이디어는 다음과 같다.
- 배열의 각 행의 0번부터 n - 1번까지 체크해준다.
- 체크 중에 현재 인덱스의 높이와 이전의 높이가 다를 때, 세가지 경우로 다시 나눠준다.
- 현재 높이가 이전 높이보다 크다면, 경사의 길이만큼 이전의 개수를 체크해서 높이가 다 같은지 확인하고, 다 같으면 경사로를 깔아준다. 그렇지 않다면 전체 answer 개수를 1개 빼주고 현재 행에 대한 탐색을 끝낸다.
- 현재 높이가 이전 높이보다 작다면, 경사의 길이만큼 다음의 개수를 체크해서 높이가 다 같은지 확인하고, 다 같으면 경사로를 깔아준다. 그렇지 않다면 전체 answer 개수를 1개 빼주고 현재 행에 대한 탐색을 끝낸다.
- 현재 높이와 이전 높이의 차이가 1보다 크면, 전체 answer 개수를 1개 빼주고 현재 행에 대한 탐색을 끝맞춘다.
- 행에 대한 탐색이 모두 끝났으면, 열에 대한 탐색도 위와 똑같이 해준다.
// // 14890.cpp // BJ // // Created by 신기열 on 25/10/2019. // Copyright © 2019 신기열. All rights reserved. // #include <stdio.h> #include <iostream> using namespace std; int map[101][101]; int answer; int visited[101]; int n, L; int main(){ cin >> n >> L; for(int i = 0; i < n; i++){ for(int j = 0; j < n; j++){ cin >> map[i][j]; } } answer = n * 2; // 모든 행에 대하여 for(int i = 0; i < n; i++){ //cout << i << "행 : "; int flag = 0; // 가로 한줄 쭉 훑어볼 떄 int j = 1; for(int i = 0; i < n; i++){ visited[i] = 0; } while(j < n){ //cout << j << "번째 탐색" << '\n'; // 높이 : 탐색 기준 왼쪽 int h = map[i][j - 1]; // 높이가 같지 않다면 if(map[i][j] != h){ // 오른쪽이 왼쪽보다 1 높을 때 if(map[i][j] == h + 1){ for(int k = 1; k <= L; k++){ if(j - k < 0 || j - k >= n || (j - k >= 0 && j - k < n && (map[i][j - k] != h || visited[j - k] == 1))){ answer--; flag = 1; break; } } if(flag == 0){ for(int k = 1; k <= L; k++){ visited[j - k] = 1; } j++; } } // 오른쪽이 왼쪽보다 1 낮을 때 else if(map[i][j] == h - 1){ int ch = map[i][j]; for(int k = 0; k < L; k++){ if(j + k < 0 || j + k >= n || (j + k >= 0 && j + k < n && (map[i][j + k] != ch || visited[j + k] == 1))){ answer--; flag = 1; break; } } if(flag == 0){ for(int k = 0; k < L; k++){ visited[j + k] = 1; } j += L; } } else{ answer--; break; } } else j++; if(flag == 1){ j++; //cout << "길이 아닙니다. answer : " << answer << '\n'; break; } } } // 모든 열에 대하여 for(int i = 0; i < n; i++){ //cout << i << "열 : "; int flag = 0; // 가로 한줄 쭉 훑어볼 떄 int j = 1; for(int i = 0; i < n; i++){ visited[i] = 0; } while(j < n){ //cout << j << "번째 탐색 : "; // 높이 : 탐색 기준 왼쪽 int h = map[j - 1][i]; // 높이가 같지 않다면 if(map[j][i] != h){ // 오른쪽이 왼쪽보다 1 높을 때 if(map[j][i] == h + 1){ for(int k = 1; k <= L; k++){ if(j - k < 0 || j - k >= n || (j - k >= 0 && j - k < n && (map[j - k][i] != h || visited[j - k] == 1))){ answer--; flag = 1; break; } } if(flag == 0){ for(int k = 1; k <= L; k++){ visited[j - k] = 1; } j++; } } // 오른쪽이 왼쪽보다 1 낮을 때 else if(map[j][i] == h - 1){ int ch = map[j][i]; for(int k = 0; k < L; k++){ if(j + k < 0 || j + k >= n || (j + k >= 0 && j + k < n && (map[j + k][i] != ch || visited[j + k] == 1))){ answer--; flag = 1; break; } } if(flag == 0){ for(int k = 0; k < L; k++){ visited[j + k] = 1; } j += L; } } else{ answer--; break; } } else j++; if(flag == 1){ j++; //cout << "길이 아닙니다. answer : " << answer << '\n'; break; } } } cout << answer; return 0; }
댓글
댓글 쓰기