1068 Find More Coins (30分) 01揹包+路徑
阿新 • • 發佈:2020-08-26
題目
https://pintia.cn/problem-sets/994805342720868352/problems/994805402305150976
題意
N個硬幣,選出一些,剛好湊成M元
按01揹包求解,揹包容量M,若能裝滿,說明有解
若有多解,輸出序列最小的(難點)
Sample Input 1:
8 9
5 9 8 7 2 3 4 1
Sample Output 1:
1 3 5 (2 3 4、9...)
Sample Input 2:
4 8
7 2 4 3
Sample Output 2:
No Solution
思路
對01揹包演算法改進下,序列降序排序
標記f[][]
參考:https://www.liuchuo.net/archives/2323
code
#include <bits/stdc++.h> using namespace std; typedef long long ll; int N,M; int w[10006]; int dp[10006][101];//前i個硬幣選出價值為j的 int f[10006][101]; bool cmp(int x,int y) {return x>y;} int main() { cin>>N>>M; for(int i=1;i<=N;++i) cin>>w[i]; sort(w+1,w+1+N,cmp); for(int i=1;i<=N;++i) { for(int j=M;j>=0;--j) { if(j>=w[i]) { if(dp[i-1][j]<=dp[i-1][j-w[i]]+w[i]) { dp[i][j]=dp[i-1][j-w[i]]+w[i]; f[i][j]=1; } else dp[i][j]=dp[i-1][j]; } else dp[i][j]=dp[i-1][j]; } } vector<int>ans; if(dp[N][M]==M) { int i=N,j=M; while(j>0) { if(f[i][j]) { ans.push_back(w[i]); j-=w[i]; } i--; } for(int i=0;i<ans.size();++i) { cout<<ans[i]; if(i!=ans.size()-1) cout<<" "; } } else cout<<"No Solution"; return 0; }