백준 - 빗물(14719)

정민주·2023년 11월 27일

코테

목록 보기
2/95

해당 문제는 초기설계를 잘못 잡아서 고생했다가 로직을 갈고 성공했다.


📒목표

모든 벽을 한 번씩만 방문하여 빗물 계산하기!

🚨문제의 초기설계

일단 나는 빗물의 형태를 다음과 같이 나누었다.
-> 참고로 평행은 오름차순과 동일한 로직으로 빗물을 계산해주었다.

빗물을 계산해주는 방법은 다음과 같다.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
    static int RAIN = 0;
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        br.readLine();
        String[] W = br.readLine().split(" ");
        int[] wall = new int[W.length];
        for (int i = 0; i < W.length; i++) {
            wall[i] = Integer.parseInt(W[i]);
        }
        for(int i=0;i<wall.length-1; i++){
            i = CheckRain(i, wall);
        }
        System.out.println(RAIN);
    }
    public static int CheckRain(int start, int[] wall) {
        int sumBlock = 0;
        int highest = 0;
        int move = 0;
        int i = start + 1;
        for (; i < wall.length && wall[start] > wall[i]; i++) {
            highest = Math.max(highest, wall[i]);
            if(highest > wall[i]) continue;
            move++;
            sumBlock+=wall[i];
        }
        if(i==wall.length) i--;
        highest = Math.max(highest,wall[i]);
        highest = Math.min(wall[start], highest); //내림차순의 경우 정확한 highest 계산 위한 코드
        if(wall[start] >= wall[highest]&&highest!=0) {
            sumBlock -= highest;
            move-=1;
        }
        RAIN += highest*move - sumBlock;
        return start+move+1;
    }
}

그러나ㅠ 빗물에 대한 2가지 형태를 하나의 for문으로 수행하고자 하니 수없이 생기는 if문들과 반례들로 인해 해당 로직은 구현하지 못하였다😢

그래서 새롭게 로직을 갈게 되었다


❤️정답 설계

빗물의 형태

빗물의 형태는 초기 설계와 같다.

  1. 오름차순
  2. 오름차순->내림차순
  3. 내림차순
  4. 평행(n개의 가장 높은 벽의 길이가 동일한 경우)

⭐ 내림차순->오름차순의 경우는 없다.

계산 로직

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {
    static int RAIN = 0;
    public static void main(String[] args) throws IOException {

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        br.readLine();
        String[] W = br.readLine().split(" ");
        int[] wall = new int[W.length];
        int Biggest = 0;
        int BiggestIndex = 0;
        for (int i = 0; i < W.length; i++) {
            wall[i] = Integer.parseInt(W[i]);
            if(wall[i]>=Biggest) {
                Biggest=wall[i];
                BiggestIndex = i; //가장 큰 값을 가지게 될 값의 제일 마지막 인덱스 저장
            }
        }
        CheckRain(BiggestIndex, wall); //순방향 체크
        CheckRainReverse(BiggestIndex, wall); //역순으로 체크
        System.out.println(RAIN);
    }

    public static void CheckRain(int BiggestIndex, int[] wall) { //오름차순 형태 계산
        for(int i=0; i<BiggestIndex; i++){
            if(wall[i]>wall[i+1]){
                RAIN += wall[i]-wall[i+1];
                wall[i+1] = wall[i];
            }
        }
    }

    public static void CheckRainReverse(int BiggestIndex, int[] wall) { //내림차순 형태 계산
        for(int i= wall.length-1; i>BiggestIndex; i--){
            if(wall[i]>wall[i-1]){
                RAIN += wall[i]-wall[i-1];
                wall[i-1] = wall[i];
            }
        }
    }

}

시간 복잡도

O(n)이다.

업로드중..

🤔후기

로직을 바꾸니 너무 단시간에 성공해서 허무했다. 초기 설계는 중요하다는 걸 다시 느꼈다~

0개의 댓글