본문 바로가기
Develop/백준 (Cpp)

[백준] 24954번 : 물약 구매 (C++)

by Tarra 2024. 2. 24.

24954번 : 물약 구매


문제)

준겸이는 모험가이다. 모험을 떠나기 위해서는 철저한 사전 준비를 갖추어야 한다.

준겸이는 모험을 떠나기 전 종류의 물약을 모두 구매하려고 한다. 물약 상점에 들른 준겸이는 각 물약이 번부터 번까지 번호가 매겨져 있다는 것을 알아냈다. 그런데, 물약 상점에서는 오늘 특별한 이벤트를 하고 있었다. 특정 물약을 구매하면, 어떤 다른 물약들을 할인해준다는 것이었다.

 

원래 번째 물약의 가격은 동전 개이다. 만약 번째 물약을 구매하면, 종류의 다른 물약의 가격이 내려간다.

 

할인은 중첩된다. 예를 들어 1번 물약을 구매하면 3번 물약의 가격이 동전 1개만큼 할인되고, 2번 물약을 구매하면 역시 3번 물약의 가격이 동전 2개만큼 할인된다고 하자. 그러면 두 물약을 모두 구매하고 나서 3번 물약을 구매할 때 동전 3개만큼의 할인을 받을 수 있다. 단, 물약의 가격이 내려가더라도 0 이하로 내려가지는 않는다. 예를 들어, 원래 가격이 동전 5개인 물약이 동전 4개를 넘는 만큼 할인되더라도 가격은 동전 1개가 된다. 

 

준겸이는 신나서 물약을 구매하려다가, 물약을 구매하는 순서가 중요하다는 사실을 깨달았다. 준겸이를 위해 물약을 가장 싸게 샀을 때 그 비용을 알려주자.

 

 

 

입력 :

 

 

 

출력 :

첫째 줄에 물약을 가장 싸게 샀을 때 동전이 몇 개 필요한지 출력한다. 

 

 

 

 

 

풀이)

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
// 24954. 물약 구매
#include <iostream>
#include <vector>
#include <limits.h>
 
using namespace std;
 
int n;
vector<int> price;
vector<vector<pair<intint>>> sale;
vector<bool> visited;
 
vector<int> vec;
int ans = INT_MAX;
void recur(int cur)
{
    // 조합이 완성되었다면
    if (cur == n)
    {
        int res = 0;
        // 원본 가격은 바꾸면 안되므로 복사한다.
        vector<int> temp = price;
        
        // 순서대로 물약을 구매하면서, 할인을 적용한다.
        for (int i = 0; i < n; i++)
        {
            int cur = vec[i];
            res += temp[cur];
 
            for (int j = 0; j < sale[cur].size(); j++)
            {
                int x = sale[cur][j].first;
                int y = sale[cur][j].second;
                temp[x] -= y;
                temp[x] = max(1, temp[x]);
            }
        }
 
        ans = min(ans, res);
        return;
    }
 
    // 물약에 대한 조합
    for (int i = 0; i < n; i++)
    {
        // 해당 물약을 구매했는지 아닌지.
        if (visited[i] == truecontinue;
        visited[i] = true;
        vec[cur] = i;
        recur(cur + 1);
        visited[i] = false;
    }
}
 
int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(0);
 
    cin >> n;
 
    price.resize(n);
    sale.resize(n);
 
    vec.resize(n);
    visited.resize(n, false);
 
    for (int& ele : price) cin >> ele;
 
    int t, a, b;
    for (int i = 0; i < n; i++)
    {
        cin >> t;
        for (int j = 0; j < t; j++)
        {
            cin >> a >> b;
            sale[i].push_back(make_pair(a - 1, b));
        }
    }
 
    recur(0);
 
    cout << ans;
 
    return 0;
}
 
cs

출처 : https://www.acmicpc.net/problem/24954 

 

24954번: 물약 구매

동전 10개를 지불하고 1번 물약을 구매하면, 3번 물약이 동전 10개만큼 할인되어 값이 동전 10개가 된다. 2번 물약은 동전 20개만큼 할인되어야 하지만, 최소 1개는 지불해야 하므로 값이 동전 1개가

www.acmicpc.net