-
728x90
문제 접근 방식은 아래와 같다.
- int[][] board : 각 위치의 높이를 저장할 2차원 배열
- boolean[][] isPlaced : 각 위치에 경사로 배치 여부를 저장할 2차원 배열
문제에서 길은 행 단위로 N개, 열 단위로 N개 존재해 총 2N개의 길을 검사해야 한다. 따라서 행 단위로 먼저 0행부터 N-1행까지 각 길이 지나갈 수 있는지를 확인하고, 이후 열 단위로 0열부터 N-1열까지 각 길이 지나갈 수 있는지 검사하도록 코드를 작성했다.
여기서 유의할 점은 행 단위로 검사하면서 한 위치에 경사로를 넣었더라도, 열 단위로 검사할 때 이전에 행 단위 검사에서 넣은 경사로는 고려하지 않아야 한다. (각 길이 지나갈 수 있는지 여부를 체크하는 것이기 때문) 그래서 행 단위 검사가 끝나고 열 단위 검사를 시작하기 전에, isPlaced 배열은 새로 초기화해준다.
먼저, 행 단위 검사 코드는 아래와 같다.
// 행 기준 검사for(int i = 0; i < N; i++) {boolean isPossible = true;for(int j = 0; j < N - 1; j++) {// 경사가 1 차이나는 지점을 만나면if(Math.abs(board[i][j] - board[i][j + 1]) == 1) {// 좌상향 경사로인 경우// 경사로를 놓을 수 있는 길이가 부족하거나,if(board[i][j] > board[i][j + 1]) {if(j + L > N - 1) {isPossible = false;continue;}// 그 길이의 블록에 이미 놓아진 경사로가 이미 있거나, 높이가 1 낮은 블록들이 아니라면 불가for(int k = 1; k <= L; k++) {if(isPlaced[i][j + k] || board[i][j + k] + 1 != board[i][j]) {isPossible = false;break;}}if(isPossible) {for(int k = 1; k <= L; k++) {isPlaced[i][j + k] = true;}}}else { // 우상향 경사로인 경우if(j - L + 1 < 0) {isPossible = false;continue;}for(int k = 0; k < L; k++) {if(isPlaced[i][j - k] || board[i][j - k] + 1 != board[i][j + 1]) {isPossible = false;break;}}if(isPossible) {for(int k = 0; k < L; k++) {isPlaced[i][j - k] = true;}}}}else if(Math.abs(board[i][j] - board[i][j + 1]) > 1) {isPossible = false;}}// 경사로를 놓을 수 있거나, 모두 높이가 같다면 answer 증가if(isPossible) {answer++;}}- 행, 열 순으로 이중 반복문을 배치해서 높이의 차가 1 차이나면, 경사로를 배치할지 여부를 검사한다. 경사로 배치를 고려할 때는, 오른쪽의 높이가 높은지, 왼쪽의 높이가 높은지를 구분해야 한다. 경사로 배치 방향이 달라지기 때문이다.
- 만약 오른쪽의 높이가 높다면, 왼쪽에 경사로를 배치한다. 따라서 경사로의 길이 L만큼 놓을 여유가 있는지를 먼저 검사해보고, 여유가 있다면 경사로를 놓는 그 위치들에 이미 놓은 경사로는 없는지, 또 높이가 일정한지를 확인해야 한다.
- 만약 위 모든 조건들을 통과해서 경사로를 놓을 수 있다면, isPlaced 배열에 true 값을 넣어주며 경사로를 놓는다.
위 단계들은 다시 열 단위 검사할 때도 유사하게 적용되므로 약간의 수정만 거쳐서 코드를 추가적으로 작성해주면 된다.
전체 풀이 코드는 아래와 같다.
import java.io.BufferedReader;import java.io.InputStreamReader;import java.util.StringTokenizer;public class Main {static int N, L, answer;static int[][] board;static boolean[][] isPlaced;public static void main(String[] args) throws Exception{BufferedReader br = new BufferedReader(new InputStreamReader(System.in));StringTokenizer st = new StringTokenizer(br.readLine());N = Integer.parseInt(st.nextToken());L = Integer.parseInt(st.nextToken());board = new int[N][N];isPlaced = new boolean[N][N];for(int i = 0; i < N; i++) {st = new StringTokenizer(br.readLine());for(int j = 0; j < N; j++) {board[i][j] = Integer.parseInt(st.nextToken());}}// 행 기준 검사for(int i = 0; i < N; i++) {boolean isPossible = true;for(int j = 0; j < N - 1; j++) {// 경사가 1 차이나는 지점을 만나면if(Math.abs(board[i][j] - board[i][j + 1]) == 1) {// 좌상향 경사로인 경우// 경사로를 놓을 수 있는 길이가 부족하거나,if(board[i][j] > board[i][j + 1]) {if(j + L > N - 1) {isPossible = false;continue;}// 그 길이의 블록에 이미 놓아진 경사로가 이미 있거나, 높이가 1 낮은 블록들이 아니라면 불가for(int k = 1; k <= L; k++) {if(isPlaced[i][j + k] || board[i][j + k] + 1 != board[i][j]) {isPossible = false;break;}}if(isPossible) {for(int k = 1; k <= L; k++) {isPlaced[i][j + k] = true;}}}else { // 우상향 경사로인 경우if(j - L + 1 < 0) {isPossible = false;continue;}for(int k = 0; k < L; k++) {if(isPlaced[i][j - k] || board[i][j - k] + 1 != board[i][j + 1]) {isPossible = false;break;}}if(isPossible) {for(int k = 0; k < L; k++) {isPlaced[i][j - k] = true;}}}}else if(Math.abs(board[i][j] - board[i][j + 1]) > 1) {isPossible = false;}}// 경사로를 놓을 수 있거나, 모두 높이가 같다면 answer 증가if(isPossible) {answer++;}}// 경사로 초기화isPlaced = new boolean[N][N];// 열 기준 검사for(int j = 0; j < N; j++) {boolean isPossible = true;for(int i = 0; i < N - 1; i++) {// 경사가 1 차이나는 지점을 만나면if(Math.abs(board[i][j] - board[i + 1][j]) == 1) {// 경사로를 놓을 수 있는 길이가 부족하거나,if(board[i][j] > board[i + 1][j]) {if(i + L > N - 1) {isPossible = false;continue;}// 그 길이의 블록에 이미 놓아진 경사로가 이미 있거나, 높이가 1 낮은 블록들이 아니라면 불가for(int k = 1; k <= L; k++) {if(isPlaced[i + k][j] || board[i + k][j] + 1 != board[i][j]) {isPossible = false;break;}}if(isPossible) {for(int k = 1; k <= L; k++) {isPlaced[i + k][j] = true;}}}else {if(i - L + 1 < 0) {isPossible = false;continue;}for(int k = 0; k < L; k++) {if(isPlaced[i - k][j] || board[i - k][j] + 1 != board[i + 1][j]) {isPossible = false;break;}}if(isPossible) {for(int k = 0; k < L; k++) {isPlaced[i - k][j] = true;}}}}else if(Math.abs(board[i][j] - board[i + 1][j]) > 1) {isPossible = false;}}// 경사로를 놓을 수 있거나, 모두 높이가 같다면 answer 증가if(isPossible) {answer++;}}System.out.println(answer);} // end of main}'Algorithms' 카테고리의 다른 글
[BOJ] 14503번 로봇청소기 Java 풀이 (0) 2021.06.19 [BOJ] 14502번 연구소 Java 풀이 (0) 2021.06.19 [BOJ] 13460 구슬 탈출2 Java 풀이 (0) 2021.06.09 [프로그래머스] 카펫 Java 풀이 (0) 2021.05.07 [프로그래머스] 소수 찾기 Java 풀이 (0) 2021.05.07