Algorithm

백준 11052번 <카드 구매하기>

seungh2 2022. 4. 28. 15:28

백준 알고리즘 11052번

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

 

11052번: 카드 구매하기

첫째 줄에 민규가 구매하려고 하는 카드의 개수 N이 주어진다. (1 ≤ N ≤ 1,000) 둘째 줄에는 Pi가 P1부터 PN까지 순서대로 주어진다. (1 ≤ Pi ≤ 10,000)

www.acmicpc.net


11052번

민규는 같은 n개를 사도 비싸게 사면 좋은 카드가 더 많이 들었을 거라고 생각한다.

주어진 카드 개수를 제일 비싸게 살 수 있을 때 얼마가 드는지 구하여라.

 

입력으로 첫 줄에 카드 팩의 개수 n이 들어온다. 그리고 그 다음 줄에 n개의 정수가 들어온다.

(카드 팩은 각각 1개, 2개, 3개 ... n개로 구성되어 있고 들어온 정수는 각 카드 팩의 금액이다.)

만약 카드의 개수가 n이고, 1 2 3이 들어온다면 1은 카드 1개를 사는데 금액은 1이고, 카드 2개를 사는데 금액은 2, 카드 3개를 사는데 금액은 3이라는 의미이다.

 

출력으로 카드 n개를 살 때, 가장 비싸게 사는 금액을 출력하면 된다.


문제 해결

다이나믹 프로그래밍으로 풀 수 있다.

 

메모제이션하는 테이블을 dp라고 정의했다.

dp[i]는 i개의 카드를 사는데 드는 금액의 최댓값이다.

(모든 배열은 1 indexed로 맞추었다.)

 

dp[1]은 cards[1]이다.

dp[i]는 dp[1] * i와 dp[1] + dp[i-1], dp[2][ + dp[i-2] ... , cards[i] 중 큰 값이다.

굵은 글씨로 표시한 부분은 앞의 index가 뒤의 index보다 작을 때만 진행한다.


코드

package bj11052;

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

public class Main {

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

		int n = Integer.parseInt(br.readLine());
		int[] cards = new int[n + 1];
		cards[0] = 0;
		String[] inArr = new String[n];
		inArr = br.readLine().split(" ");
		for (int i = 1; i < n + 1; i++) {
			cards[i] = Integer.parseInt(inArr[i - 1]);
		}
		int[] dp = new int[n + 1];
		dp[0] = cards[0];
		dp[1] = cards[1];

		for (int i = 2; i < n + 1; i++) {
			int temp = cards[1] * i;
			temp = Math.max(temp, cards[i]);
			for (int j = 1; j < i; j++) {
				int a = i - j;
				if (a < j) {
					break;
				}
				temp = Math.max(temp, dp[j] + dp[a]);
			}
			dp[i] = temp;
		}

		System.out.println(dp[n]);

	}

}

코드(23.01.04)

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.Array;
import java.util.Arrays;

/*
* 다이나믹 프로그래밍으로 풀 수 있다.
* dp[i] : i개의 카드를 뽑는데 드는 최대 금액
* dp[i] : max(dp[1] + dp[i-1], dp[2] + dp[i-2], ... , dp[i/2] + dp[i-i/2], prices[i])
*
* N의 최대 수가 1000이기 때문에
* 최대 금액은 1,000 * 10,000 = 10,000,000 이기 때문에 int 형 사용
*
* dp[1000]을 구하기 위해서
* 500의 연산 필요
* dp 배열의 값을 구할 때 모두 500의 연산을 한다고 가정하면
* 500 * 1,000 = 500,000의 연산 필요.
* */
public class BOJ11052 {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int N = Integer.parseInt(br.readLine());       // N : 카드의 개수
        String[] inArr = br.readLine().split(" ");
        int[] prices = new int[N+1];    // prices[i] : i개의 카드가 들은 카드팩의 가격
        for(int i = 0; i < N; i++){
            prices[i+1] = Integer.parseInt(inArr[i]);
        }

        int[] dp = new int[N+1];    // dp[i] : i개의 카드를 뽑는데 드는 최대 금액
        dp[1] = prices[1];

        for(int i = 2; i <= N; i++){
            for(int j = 1; j <= i / 2; j++){
                dp[i] = Math.max(dp[i], dp[j] + dp[i-j]);
            }
            dp[i] = Math.max(dp[i], prices[i]);
        }
        System.out.println(dp[N]);
    }
}
/*
5
1 10 1 1 1
21
-----------------
6
3 4 2 8 4 20
20
-----------------
6
3 4 2 8 4 10
18

* */

결과


 

728x90