1068 Find More Coins (30分) 01背包+路径
题目
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;
}