개발하는 사막여우
개발하는 사막여우
개발하는 사막여우
전체 방문자
오늘
어제
  • All (310)
    • Books (13)
      • 읽기 좋은 코드가 좋은 코드다 (13)
    • Study (6)
      • Blockchain (3)
      • Algorithm (3)
    • Baekjoon (36)
    • Programmers (166)
    • LeetCode (15)
    • Open Source (1)
      • Youtube Popout Player (1)
    • Language (32)
      • Python (9)
      • JS (8)
      • Java (5)
      • HTML (6)
      • CSS (4)
    • Library & Framework (15)
      • React.js (15)
    • IDE (2)
      • IntelliJ (2)
    • Airdrop (9)
    • Tistory (2)
    • etc.. (12)
      • Cozubi (6)
      • lol-chess (0)

블로그 메뉴

  • Github

공지사항

인기 글

태그

  • 2018 KAKAO BLIND RECRUITMENT
  • 알고리즘문제풀이
  • 코주비
  • Cozubi
  • programmers
  • 읽기 좋은 코드가 좋은 코드다
  • Python
  • 프로그래머스
  • 카카오 공채
  • Java
  • 카카오 코딩테스트
  • 클린 코드 작성법
  • 파이썬
  • 코인줍줍
  • 카카오 알고리즘 문제
  • 백준
  • 프로그래머스 위클리 챌린지
  • 코딩테스트연습
  • 신규 코인 에어드랍
  • 클린 코드

최근 댓글

최근 글

티스토리

반응형
hELLO · Designed By 정상우.
개발하는 사막여우

개발하는 사막여우

[프로그래머스] 지형 편집 / Java
Programmers

[프로그래머스] 지형 편집 / Java

2021. 4. 6. 15:53
반응형

문제주소 :programmers.co.kr/learn/courses/30/lessons/12984

 

코딩테스트 연습 - 지형 편집

XX 게임에서는 지형 편집 기능을 이용하여 플레이어가 직접 게임 속 지형을 수정할 수 있습니다. 이 게임에서는 1 x 1 x 1 크기의 정육면체 블록을 쌓아 게임 속 지형을 표현합니다. 이때, 블록이

programmers.co.kr


<문제 설명>

더보기

문제 설명

XX 게임에서는 지형 편집 기능을 이용하여 플레이어가 직접 게임 속 지형을 수정할 수 있습니다. 이 게임에서는 1 x 1 x 1 크기의 정육면체 블록을 쌓아 게임 속 지형을 표현합니다. 이때, 블록이 공중에 떠 있거나, 블록 하나가 여러 개의 칸에 걸쳐 놓일 수는 없습니다. 따라서 지형을 편집하기 위해서는 각 칸의 제일 위에 블록 1개를 새로 추가하거나, 제일 위에 있는 블록 한 개를 삭제하는 방식으로 지형을 수정해야 합니다. 이때, 블록 한 개를 새로 추가하거나 삭제하기 위해서는 게임머니를 사용해야 하므로 몇 개의 블록을 추가하고 삭제할지 신중한 선택이 필요합니다.

이 게임을 즐기던 한 플레이어는 N x N 크기의 지역에 자신만의 별장을 만들고 싶어졌습니다. 이를 위해서는 울퉁불퉁한 지형의 모든 칸의 높이가 같아지도록 만들어야 합니다. 이때, 블록 한 개를 추가하려면 P의 비용이, 제거하려면 Q의 비용이 들게 됩니다.
다음은 블록 한 개를 추가할 때 5의 비용이, 제거할 때 3의 비용이 드는 경우, 3 x 3 넓이의 모든 칸의 블록 높이가 같아지도록 만드는 예시입니다.

위 그림과 같이 지형 블록이 놓여 있는 경우 모든 칸의 높이가 3으로 같아지도록 한다면 다음과 같은 모양이 됩니다.

이를 위해서는 3보다 높은 칸의 블록 2개를 제거하고, 3보다 낮은 칸에 총 8개의 블록을 추가해야 하며, 2 x 3 + 8 x 5 = 46의 비용이 들게 됩니다.

그러나 아래 그림과 같이 모든 칸의 높이가 2로 같아지도록 할 때는 6개의 블록을 제거하고, 3개의 블록을 추가하면 6 x 3 + 3 x 5 = 33의 비용이 들게 되며, 이때가 최소비용이 됩니다.

현재 지형의 상태를 나타내는 배열 land와 블록 한 개를 추가하는 데 필요한 비용 P, 블록 한 개를 제거하는 데 필요한 비용 Q가 매개변수로 주어질 때, 모든 칸에 쌓여있는 블록의 높이가 같아지도록 하는 데 필요한 비용의 최솟값을 return 하도록 solution 함수를 완성해 주세요.

제한사항

  • land는 N x N 크기의 2차원 배열이며, N의 범위는 1 ≤ N ≤ 300입니다.
  • land의 각 원소는 각 칸에 놓여 있는 블록의 수를 나타내며, 0 이상 10억 이하의 정수입니다.
  • 각 칸에 블록 하나를 추가하는 데는 P, 제거하는 데는 Q의 비용이 들며, P, Q의 범위는 1 ≤ P, Q ≤ 100인 자연수입니다.

입출력 예

land                               P                                   Q                                   result
[[1, 2], [2, 3]] 3 2 5
[[4, 4, 3], [3, 2, 2], [ 2, 1, 0 ]] 5 3 33

입출력 예 설명

입출력 예 #1

  • 모든 땅의 높이를 1로 맞추는 데는 블록 4개를 제거해야 하므로 8의 비용이 듭니다.
  • 모든 땅의 높이를 2로 맞추는 데는 블록 1개를 추가하고 블록 1개를 제거해야 하므로 5의 비용이 듭니다.
  • 모든 땅의 높이를 3으로 맞추는 데는 블록 4개를 추가해야 하므로 12의 비용이 듭니다.

따라서 최소 비용은 5이므로 5를 return 합니다.

입출력 예 #2
문제의 예시와 같으며 최소 비용은 33입니다.

 

<풀이법>

▒ 한줄 개념: 이분 탐색 ▒ 

이분탐색 알고리즘을 사용하여 푸는 문제이다. 아래 블로그를 참고했다.

comyoung.tistory.com/166

 

[프로그래머스] 지형 편집

문제) https://programmers.co.kr/learn/courses/30/lessons/12984 풀이) 이분 탐색을 활용해서 푼 문제이다. land 중 가장 적은 높이를 start, 가장 큰 높이를 end라고 할 때 비용을 계산해 볼 기준 높이 mid는..

comyoung.tistory.com

풀이방식은 다음과 같다.

 

1. 현재 지형 중 최소높이, 최대높이를 구한다. 이분탐색 범위인 start = 최소높이 / end = 최대높이가 된다.

2. 해당 범위내에서 이분탐색을 진행하는데, mid = (start+end) / 2 이다. mid, mid+1 을 가지고 각각의 비용을 구하고, mid > mid+1 일 경우 탐색 범위가 mid+1 ~ end가 된다. 반대로 mid < mid + 1 일 경우 탐색 범위가 start ~ mid가 된다.

 

주의사항으로, 모든 변수는 long으로 선언한다. 각 블록의 높이가 최대 10억이 가능하기 때문에, int로 하면 계산이 정확하지 않을 수 있다. 처음에 start, end, mid를 int로 선언해주었더니 효율성 1~5번이 틀렸다. int값이 담을 수 없는 값이 계산되면서 오류가 발생한 것 같다. 분명 int로 21억까지 가능할텐데.. 원인은 잘 모르겠지만 long으로 모든 변수를 선언해야 다 통과할 수 있다.

 

이분탐색이 개념은 굉장히 쉬운 알고리즘인데, +1, -1 하는 과정에서 한틱의 오류가 사람을 좀 괴롭게 만드는 것 같다. 추상적으로는 구현이 쉽지만, 한칸한칸 계산하는 것이 머릿속에서 오류를 좀 일으킨다. 이분탐색 문제를 좀 더 풀어봐야 할 것 같다.

 

<코드(Java)>

public class Solution {
        int[][] land;
        int P,Q;
        int N;
        
        public long solution(int[][] land, int P, int Q) {
            long answer = 0;
            
            this.land = land;
            this.P = P;
            this.Q = Q;
            this.N = land.length;
            
            long end = this.land[0][0]; 
            long start = this.land[0][0];
            for(int i = 0; i < this.N; i++){
                for(int j = 0; j < this.N; j++){
                    if(this.land[i][j] > end)
                        end = this.land[i][j];
                    if(this.land[i][j] < start)
                        start = this.land[i][j];
                }
            }
            
            long mid;
            while(start <= end){
                
                mid = (start + end)/ 2;
                
                long leftCost = calculateCost(mid);
                long rightCost = calculateCost(mid+1);
                
                if(leftCost > rightCost){
                    answer = rightCost;
                    start = mid+1;
                }
                else{
                    answer = leftCost;
                    end = mid-1;
                }
            }
            
            return answer;
        }
        
        long calculateCost(long height){
            long cost = 0;
            for(int i = 0; i < this.N; i++){
                for(int j = 0; j < this.N; j++){
                    if(land[i][j] > height){
                        cost += (land[i][j] - height) * Q; 
                    }
                    else{
                        cost += (height - land[i][j]) * P;
                    }
                }
            }
            return cost;
        }
    }

 

 

더 많은 코드 보기(GitHub) : github.com/dwkim-97/CodingTest

 

 

반응형
저작자표시 (새창열림)

'Programmers' 카테고리의 다른 글

[프로그래머스] 음양 더하기 / Java, JavaScript  (0) 2021.04.20
[프로그래머스] 리틀 프렌즈 사천성 / Java  (2) 2021.04.07
[프로그래머스] 쿠키 구입 / Java  (0) 2021.04.05
[프로그래머스] 지형 이동 / Java  (0) 2021.04.04
[프로그래머스] 동굴 탐험 / Java  (0) 2021.04.01
    'Programmers' 카테고리의 다른 글
    • [프로그래머스] 음양 더하기 / Java, JavaScript
    • [프로그래머스] 리틀 프렌즈 사천성 / Java
    • [프로그래머스] 쿠키 구입 / Java
    • [프로그래머스] 지형 이동 / Java
    개발하는 사막여우
    개발하는 사막여우
    개발개발 주저리주저리

    티스토리툴바