PAT甲级1068 Find More Coins【01背包】

题目https://pintia.cn/problem-sets/994805342720868352/problems/994805402305150976

题意

n个硬币,每一个有一个特有的价值,一个硬币只有一个,要求选取一些硬币使得他们的价值刚好是m

输出字典序最小的方案。

思路:

最近好久没有刷题了连PAT都好久没动了这样不行啊。连背包都有点不大会了。赶紧把PAT30分的刷完去刷洛谷了。

硬币是一个weight和value相同的物品,背包的容量就是m

问题转换成尽量让包中的价值大,背包中的最大价值都无法到达m说明没有答案。

价值是不可能超过m的,因为weight和value相同,weight限制了。

用一个bool二维数组来保存某一个方案中有没有这个硬币。

因为要求输出字典序最小的方案,所以刚开始先从大到小来排序,先考察大的,当小的和当前价值一样的时候也进行更新。

这时候的更新就是将更小的一个方案进行更新。

在逆序跑bool数组存方案就行了。

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<map>
 4 #include<set>
 5 #include<iostream>
 6 #include<cstring>
 7 #include<algorithm>
 8 #include<vector>
 9 #include<cmath> 
10 #include<stack>
11 #include<queue>
12 
13 #define inf 0x7fffffff
14 using namespace std;
15 typedef long long LL;
16 typedef pair<string, string> pr;
17 
18 int n, m;
19 const int maxn = 1e4 + 5; 
20 int val[maxn];
21 bool choice[maxn][105];
22 int dp[maxn];
23  
24 bool cmp(int a, int b){
25     return a > b;
26 }
27  
28 int main()
29 {
30     scanf("%d%d", &n, &m);
31     for(int i = 0; i < n; i++){
32         scanf("%d", &val[i]);
33     }
34     sort(val, val + n, cmp);
35     for(int i = 0; i < n; i++){
36         for(int j = m; j >= val[i]; j--){
37             if(dp[j] <= dp[j - val[i]] + val[i]){
38                 choice[i][j] = true;
39                 dp[j] = dp[j - val[i]] + val[i];
40             }
41         }
42     }
43     if(dp[m] != m)printf("No Solution\n");
44     else{
45         vector<int>ans;
46         int now = m, id = n - 1;
47         while(now > 0){
48             if(choice[id][now]){
49                 ans.push_back(val[id]);
50                 now -= val[id];
51             }
52             id--;
53         }
54         printf("%d", ans[0]);
55         for(int i = 1; i < ans.size(); i++){
56             printf(" %d", ans[i]);
57         }
58         printf("\n"); 
59     }
60     return 0;
61 }

猜你喜欢

转载自www.cnblogs.com/wyboooo/p/10641538.html