파게로그

[백준 12931번] 두 배 더하기 본문

콤퓨타 왕왕기초/PS

[백준 12931번] 두 배 더하기

파게 2022. 4. 1. 06:56

문제 링크: 12931번 두 배 더하기

https://www.acmicpc.net/problem/12931

 

전형적인 DP 문제라고 생각했는데 그리디한 접근이 필요한 문제였다. 내가 헷갈렸던 것은... 어떤 양의 정수를 0으로 만들고자 할 때, 2로 나누는 편이 1을 빼는 편보다 무조건 더 빠른가에 대한 대답이었는데, 이에 대한 답은 '그렇다'이다. 헷갈릴 일이 없는 건데... 아마도 1을 더하는 연산도 있는 경우를 두고 이상한 데서 고민한 것 같다. 참고로 1을 더하는 연산이 있다면, 15 → 16 → 8 → 4 → 2 → 1 → 0이 15 → 14 → 7 → 6 → 3 → 2 → 1 → 0보다 빠르다.

먼저, 양의 정수들에 대해서, 0으로 만들기 위한 횟수를 미리 구해두어야 하는데, 단순히 횟수가 아니라 0으로 만드는 과정에서 필요한 '1 감소 연산'과 '1/2배 연산'의 횟수를 각각 구해둔다. 각 수를 2진수로 고려했을 때 0, 1의 개수 등을 고려하여 그 횟수를 구해내는 스터디원 생각이 신박했는데... 일단 여기서는 평범하게 구하도록 한다.

어떤 과정으로든 해당 결과값은 다음과 같이 나올 것이다.

 

N 1 감소 연산 1/2배 연산
1 1 0
2 1 1
3 2 0
4 1 2
5 2 2
6 2 1
7 3 1

 

그리고 배열에서 '1 감소 연산'은 각 원소에 대해 각각 시행되어야 하므로 각 원소가 필요로 하는 횟수의 합을 더해주며, '1/2배 연산'은 모든 원소에 대해 동시에 시행되므로 각 원소가 필요로 하는 횟수 중 최댓값만큼만 시행하면 된다.

동시에 1/2배를 해야하니 더 걸릴 수도 있겠다고 생각되지만, [3, 5, 7]의 상태에서는 [2, 4, 6]으로, 2로 나눌 수 있도록 1개씩 빼야하는 예시를 생각해보면, 어차피 이 횟수는 모두 '1 감소 연산'에서 합을 구했기 때문에 포함되어 있다.

 

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

public class Main {
    static int n;

    public static void main(String[] args) throws IOException {
        int[][] dp = new int[1001][2];
        // dp[i][x]: num of operations required to make 0 from i
        // x = 0 for '-1', x = 1 for '1/2'

        dp[1][0] = 1; dp[1][1] = 0;
        for (int i = 2; i <= 1000; i++) {
            if (i % 2 != 0) {
                dp[i][0] = dp[i - 1][0] + 1;
                dp[i][1] = dp[i - 1][1];
            } else {
                dp[i][0] = dp[i / 2][0];
                dp[i][1] = dp[i / 2][1] + 1;
            }
        }

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        n = Integer.parseInt(br.readLine());
        StringTokenizer st = new StringTokenizer(br.readLine(), " ");

        int sum = 0;
        int max = 0;
        int t;
        for (int i = 0; i < n; i++) {
            t = Integer.parseInt(st.nextToken());
            sum += dp[t][0];
            if (dp[t][1] > max) max = dp[t][1];
        }

        System.out.println(sum + max);
    }
}

'콤퓨타 왕왕기초 > PS' 카테고리의 다른 글

[백준 2229번] 조 짜기  (0) 2022.04.14
[백준 11967번] 불켜기  (0) 2022.04.05
[백준 22115번] 창영이와 커피  (0) 2022.03.21
[백준 11049번] 행렬 곱셈 순서  (0) 2022.03.17
[백준 1520번] 내리막 길  (0) 2022.03.16
Comments