algorithm

백준 2879(JAVA)

yjs3819 2021. 8. 31. 13:11

문제

풀이

그리디 알고리즘으로 문제자체 푸는법은 어렵지않으나 나는 너무 안일하게 생각했던 나머지 2번 틀렸다.
그리디 알고리즘 자체가 '이 문제는 그리디 알고리즘으로 푸는 것이다'라는 것을 깨닫는게 어려운거지, 깨닫고나면 푸는법은 어렵지 않은 것 같다.

하나의 편집은 연속된 줄을 그룹으로 탭을 하나 추가하거나 삭제할수 있다.
이 편집의 횟수를 최소화하라는 문제이다.
일단 입력되는 두줄의 차이를 먼저 계산했다.(모두 0 으로 바꾸는게 목적이므로)

4
5 4 5 5
1 5 0 1

4 -1 5 4

가 된다.
일단 한번의 편집에 탭을 추가하거나 뺄수 있으니 음수 양수로 나눠야겠다는 생각을 했다.
(4)
(-1)
(5, 4)
로 나뉘게 된다.

한번의 편집은 여러줄을 그룹으로 선택할수 있기에
여러줄을 한번에 1씩 더하거나 뺄수 있다.

  • (4)그룹의 모든 합을 0으로 만드려면
    4번의 편집을 걸쳐 0으로 바꿀수있고

  • (-1)그룹의 모든 합을 0으로 만드려면
    1번의 편집으로 0 으로 바꿀수있고

  • (5, 4)그룹의 모든합을 0으로 만드려면
    5번의 편집으로 0 으로 바꿀수있다.

총 10번!

즉, 양수 음수를 기준으로 최초에 구분한 그룹마다 편집을 가하는데, 편집을 하는 도중에도 그룹이 나뉠수있다. 무슨말이냐면

5
1 1 1 1 1
5 3 2 3 2

예시는 차이를 구하면 -4 -2 -1 -2 -1로
음수 양수 그룹으로 구분하면
(-4, -2, -1, -2, -1)하나이다.
하나의 편집을 가하면
(-3, -1, 0, -1, 0)이 된다.
이때 (-3, -1), (-1)이런식으로 다시 그룹이 생기게 된다.(우리는 최소의 편집횟수를 구해야하므로 그룹을 할수있으면 그룹지어서 편집을 무조건 해야한다.)

이부분을 고려하면서 코드를 작성하면 문제를 풀수있다!(나는 이부분을 생각못해서, 두번이나 틀렸다.)

코드

package baekjoon.그리디;

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

public class Main2879 {
    static int N;
    static int[] diff;

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        N = Integer.parseInt(br.readLine());
        diff = new int[N];
        int[] input = new int[N];
        int[] output = new int[N];

        StringTokenizer st = new StringTokenizer(br.readLine(), " ");
        for(int i = 0; i < N; i++){
            input[i] = Integer.parseInt(st.nextToken());
        }
        st = new StringTokenizer(br.readLine(), " ");
        for(int i = 0; i < N; i++){
            output[i] = Integer.parseInt(st.nextToken());
        }

        for(int i = 0; i < N; i++){
            diff[i] = input[i] - output[i];
        }

        System.out.println(fixIndent());
    }
    static int fixIndent(){
        int count = 0;

        List<List<Integer>> group = new ArrayList<>();
        for(int i = 0; i < N; i++){
            group.add(new ArrayList<>());
        }
        int num = 0;
        int before = 0;
        int after = 0;
        if(diff[0] > 0) before = 1;
        else if(diff[0] == 0) before = 0;
        else before = -1;
        group.get(num).add(diff[0]);

        for(int i = 1; i < diff.length; i++){
            if(diff[i] > 0){
                after = 1;
            }else if(diff[i] == 0){
                after = 0;
            }else{
                after = -1;
            }
            if(before == after){
                group.get(num).add(diff[i]);
            }else{
                num++;
                group.get(num).add(diff[i]);
            }
            before = after;
        }
        for (List<Integer> integers : group) {
            if(integers.size() == 0) break;
            int sum = integers.stream().mapToInt(Integer::intValue).sum();
            while(sum != 0){
                int startIdx = 0;
                for(int i = 0; i < integers.size(); i++){
                    if(integers.get(i) != 0) {
                        startIdx = i;
                        break;
                    }
                }
                for(int i = startIdx; i < integers.size(); i++){
                    if(integers.get(i) != 0){
                        if(integers.get(i) > 0){
                            integers.set(i, integers.get(i) - 1);
                        }else{
                            integers.set(i, integers.get(i) + 1);
                        }
                    }else break;
                }
                sum = integers.stream().mapToInt(Integer::intValue).sum();
                count++;
            }
        }

        return count;
    }
}

'algorithm' 카테고리의 다른 글

백준 1932(JAVA)  (0) 2021.09.07
백준 16236(JAVA)  (0) 2021.09.03
백준 7569(JAVA)  (0) 2021.08.29
백준 2206(JAVA)  (0) 2021.08.28
백준 16197(JAVA)  (0) 2021.08.25