01满包加记录最小路劲 L3-001. 凑零钱
过了这么久 正确理解01背包应该从记忆化搜索开始
这里对数字的取或者不取实际上就是一个01背包的模型 不过这里要求的是满包问题 那么我们动态便利的过程需要做一点 处理只有从0开始的能够向上更新
在就是一个最小路径更新 可以用排序 (排序以后最先到达的满足条件的就是我们需要的路线) 也可以多次到达的时候向小的更新
#include<iostream> #include<cstring> #include<vector> #include<algorithm> #define inf 100009 using namespace std; int n,m; int a[10001],dp[101],pre[101]; bool cmp(int x,int y) { return x<y; } int main() { cin>>n>>m; for(int i=1;i<=n;i++) cin>>a[i]; fill(dp,dp+101,-inf);//满包处理1 for(int i=0;i<=m;i++) pre[i]=i; dp[0]=0;// 满包处理2 sort(a+1,a+1+n,cmp); for(int i=1;i<=n;i++) { for(int j=m;j>=a[i];j--) { if(dp[j-a[i]] < 0) continue;// 对于没有包含的情况 直接跳过 if(dp[j] <= dp[j-a[i]]+1) { dp[j]=dp[j-a[i]]+1; if(pre[j] > j-a[i])pre[j]=j-a[i];// } } } if(dp[m] <= 0) cout<<"No Solution"<<endl; else { vector<int> line; line.clear(); int temp=m; //cout<<pre[m]<<endl; while(temp!=0) { line.push_back(temp-pre[temp]); temp=pre[temp]; } for(int j=line.size()-1;j>=0;j--) { if(j == line.size()-1 ) cout<<line[j]; else cout<<' '<<line[j]; } cout<<endl; } return 0; }