문제
요즘 민규네 동네에서는 스타트링크에서 만든 PS카드를 모으는 것이 유행이다.
PS카드는 PS(Problem Solving)분야에서 유명한 사람들의 아이디와 얼굴이 적혀있는 카드이다. 각각의 카드에는 등급을 나타내는 색이 칠해져 있고, 다음과 같이 8가지가 있다.
- 전설카드
- 레드카드
- 오렌지카드
- 퍼플카드
- 블루카드
- 청록카드
- 그린카드
- 그레이카드
카드는 카드팩의 형태로만 구매할 수 있고, 카드팩의 종류는 카드 1개가 포함된 카드팩, 카드 2개가 포함된 카드팩, ... 카드 N개가 포함된 카드팩과 같이 총 N가지가 존재한다.
민규는 지난주에 너무 많은 돈을 써 버렸다. 그래서 오늘은 돈을 최소로 지불해서 카드 N개를 구매하려고 한다. 카드가 i개 포함된 카드팩의 가격은 Pi원이다.
예를 들어, 카드팩이 총 4가지 종류가 있고, P1 = 1, P2 = 5, P3 = 6, P4 = 7인 경우에 민규가 카드 4개를 갖기 위해 지불해야 하는 금액의 최솟값은 4원이다. 1개 들어있는 카드팩을 4번 사면 된다.
P1 = 5, P2 = 2, P3 = 8, P4 = 10인 경우에는 카드가 2개 들어있는 카드팩을 2번 사면 4원이고, 이 경우가 민규가 지불해야 하는 금액의 최솟값이다.
카드 팩의 가격이 주어졌을 때, N개의 카드를 구매하기 위해 민규가 지불해야 하는 금액의 최솟값을 구하는 프로그램을 작성하시오. N개보다 많은 개수의 카드를 산 다음, 나머지 카드를 버려서 N개를 만드는 것은 불가능하다. 즉, 구매한 카드팩에 포함되어 있는 카드 개수의 합은 N과 같아야 한다.
입력
첫째 줄에 민규가 구매하려고 하는 카드의 개수 N이 주어진다. (1 ≤ N ≤ 1,000)
둘째 줄에는 Pi가 P1부터 PN까지 순서대로 주어진다. (1 ≤ Pi ≤ 10,000)
출력
첫째 줄에 민규가 카드 N개를 갖기 위해 지불해야 하는 금액의 최솟값을 출력한다.
예제 입력 1 복사
4 1 5 6 7
예제 출력 1 복사
4
N개의 카드를 사기 위한 최소한의 금액을 구하는 문제이다.
dfs + dp로 풀고 싶었는데 잘 안되었다.
bottom-up 방식이 나랑 잘 안 맞는 것 같아. top-down 위주로 연습해야겠다.
chosh95/STUDY
프로그래밍 문제 및 알고리즘 정리. Contribute to chosh95/STUDY development by creating an account on GitHub.
github.com
C++ 코드
#include <iostream>
#include <algorithm>
using namespace std;
int p[1001];
int dp[1001];
int N;
//현재 카드 몇 개인지, top-down
int dfs(int cnt) {
if (cnt <= 0) return 0;
if (dp[cnt] != 987654321) return dp[cnt];
for (int i = 1; i <= N; i++) {
if(cnt-i >= 0)
dp[cnt] = min(dp[cnt], dfs(cnt - i) + p[i]);
}
return dp[cnt];
}
//현재 카드 몇 개인지, bottom-up
int dfs2(int cnt) {
if (cnt >= N) return 0;
if (dp[cnt] != 987654321) return dp[cnt];
for (int i = 1; i <= N; i++) {
if (cnt + i <= N)
dp[cnt] = min(dp[cnt], dfs2(cnt + i) + p[i]);
}
return dp[cnt];
}
//현재 몇번째 카드를 조사중인지, 현재 카드 몇개 모았는지
int dfs3(int idx, int cnt) {
if (cnt >= N) return 0;
if (dp[cnt] != 987654321) return dp[cnt];
for (int i = idx; i <= N; i++) {
if (cnt + i <= N)
dp[cnt] = min(dp[cnt], dfs3(i, cnt + i) + p[i]);
}
return dp[cnt];
}
int main()
{
cin >> N;
dp[0] = 987654321;
for (int i = 1; i <= N; i++) {
cin >> p[i];
dp[i] = 987654321;
}
//cout << dfs(N); // top-down
//cout<< dfs2(0); //bottom-up
cout << dfs3(1, 0);
}
'알고리즘 > 백준' 카테고리의 다른 글
[백준] 더하기 2 (10823번) (0) | 2020.08.17 |
---|---|
[백준] 닉네임에 갓 붙이기 (13163번) (0) | 2020.08.17 |
[백준] 방 배정하기 (14697번) (0) | 2020.08.14 |
[백준] 공통 부분 문자열 (5582번) (0) | 2020.08.14 |
[백준] 등산 (16681번) (0) | 2020.08.13 |