L3-001 凑零钱
题解:感觉很不错的01满背包问题,dp[i]表示重i时的最多硬币数,先排序,根据题意,字典序最小那么意思就是满载的情况下硬币越多越好。那么只要01背包标记路程就可以了,最后dfs回溯。(个人感觉比别的题解乱七八糟降序排序好理解的多)。
#include<bits/stdc++.h> #pragma GCC optimize(2) #define ll long long #define rep(i,a,n) for(int i=a;i<=n;i++) #define per(i,n,a) for(int i=n;i>=a;i--) #define endl ‘\n‘ #define eps 0.000000001 #define pb push_back #define mem(a,b) memset(a,b,sizeof(a)) #define IO ios::sync_with_stdio(false);cin.tie(0); using namespace std; const int INF=0x3f3f3f3f; const ll inf=0x3f3f3f3f3f3f3f3f; const int mod=1e9+7; const int maxn=1e5+5; int a[maxn],pre[maxn],ans[maxn],dp[maxn]; void dfs(int x){ if(!pre[x]){ cout<<ans[x];return; }else{ dfs(pre[x]); cout<<" "<<ans[x]; } } int main(){ int n,m;cin>>n>>m; rep(i,1,n) cin>>a[i]; sort(a+1,a+n+1); mem(pre,-1);mem(dp,-INF); dp[0]=0; for(int i=1;i<=n;i++){ for(int j=m;j>=a[i];j--){ if(dp[j]<=dp[j-a[i]]+1){ dp[j]=dp[j-a[i]]+1; ans[j]=a[i]; pre[j]=j-a[i]; } } } if(dp[m]>0){ dfs(m); }else{ puts("No Solution"); } }
原文:https://www.cnblogs.com/Anonytt/p/13811687.html