[백준 14890] 경사로(Java)

최민길(Gale)·2023년 1월 22일
1

알고리즘

목록 보기
20/172

문제 링크 : https://www.acmicpc.net/problem/14890

이 문제는 문제의 조건대로 하나하나 구현해나가면 쉽게 풀 수 있습니다.

이 문제의 핵심은 경사로를 놓는 경우의 수를 어떤 식으로 설정하는가입니다. 경사로는 크게

  1. 현재 값보다 큰 수를 위한 경사로를 놓기
  2. 현재 값보다 작은 수를 위한 경사로를 놓기

입니다. 각 경우는 처리 방법이 살짝 다릅니다.

우선 1번의 경우, 현재 값 이전에 지나온 길이 모두 같으며 길이가 L보다 크거나 같은 경우 경사로를 놓을 수 있습니다.

하지만 2번의 경우는 조금 복잡한데요, 우선 다음 값부터 L번째 값까지 모든 수가 서로 같은지를 비교해야 합니다. 그럼 경사로를 놓을 수 있기 때문에 해당 위치로 인덱스를 옮겨주시면 됩니다. 이 때 마지막 L번째 값보다 1 작은 수로 옮겨야 하는데, 해당 로직은 반복문 내에서 진행하기 때문에 반복문이 1 증가시키는 카운트를 고려하여 1 작은 수로 옮긴 후 반복문에서 1을 증가시켜 L번째 값으로 이동하도록 설정해야 합니다.

다음은 코드입니다.

import java.util.*;
import java.io.*;

public class Main{
    static int N,L;
    static int res = 0;
    static int[][] reqH = new int[101][101];
    static int[][] reqV = new int[101][101];

    static void move(int[][] req){
        for(int i=0;i<N;i++){
            boolean canMove = true;
            int prevRoad = 1; // 현재 칸을 포함해야 하므로 1부터 시작

            for(int j=0;j<N-1;j++){
                // 현재 칸과 다음 칸의 차이 계산
                int prev = req[i][j];
                int curr = req[i][j+1];
                int diff = Math.abs(prev-curr);

                // 다음 칸과 차이가 0일 경우
                if(diff == 0){
                    // 지나온 칸의 수를 1씩 더함
                    prevRoad++;
                }

                // 다음 칸과 차이가 1일 경우
                else if(diff == 1){
                    // 다음 칸이 현재 값보다 더 클 경우
                    if(curr > prev){
                        // 지나온 칸의 수가 L과 같거나 클 경우 경사로 설치
                        if(prevRoad >= L){
                            // 지나온 칸의 수 1로 초기화
                            prevRoad = 1;
                        }
                        // L과 다를 경우 실패
                        else{
                            canMove = false;
                            break;
                        }
                    }

                    // 다음 칸이 현재 값보다 더 작을 경우
                    else{
                        // 다음 칸부터 L번째 칸까지 세서 값이 모두 똑같은지 확인
                        for(int idx=1;idx<=L;idx++){
                            // 만약 값이 다르다면 경사로를 세울 수 없어 실패
                            if(curr != req[i][j+idx]){
                                canMove = false;
                                break;
                            }
                        }

                        // 경사로를 세운 마지막으로 이동
                        j += L-1;
                        // 이전 길은 경사로이기 때문에 새로운 경사로를 추가할 수 없어 0으로 초기화
                        prevRoad = 0;
                    }
                }

                // 다음 칸과 차이가 2인 경우
                // 무조건 실패
                else if(diff >= 2){
                    canMove = false;
                    break;
                }
            }
            if(canMove){
                res++;
            }
        }
    }

    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());

        for(int i=0;i<N;i++){
            st = new StringTokenizer(br.readLine());
            for(int j=0;j<N;j++){
                // 가로 검증, 세로 검증용 맵 각각 만들기
                reqH[i][j] = Integer.parseInt(st.nextToken());
                reqV[j][i] = reqH[i][j];
            }
        }

        move(reqH);
        move(reqV);
        System.out.println(res);
    }
}

profile
저는 상황에 맞는 최적의 솔루션을 깊고 정확한 개념의 이해를 통한 다양한 방식으로 해결해오면서 지난 3년 동안 신규 서비스를 20만 회원 서비스로 성장시킨 Software Developer 최민길입니다.

0개의 댓글