** 浙大PAT甲級 1068 01揹包問題
阿新 • • 發佈:2018-12-23
這個題是dp01揹包問題,dp[i][j]表示在j容量下前i個貨幣最大利益,但是難點在如何輸出最小序列。
將輸入的數按遞減順序排序,mark[i][j]==1表示在容量為j時的最大的利益情況下,加入了第i個貨幣。
然後進行回溯輸出。
AC程式碼:
#include<iostream> #include<map> #include<cstdio> #include<algorithm> #include<queue> #include<cstring> #include<list> #include<set> #include<stack> #include<cmath> #include<vector> #define inf -100000000 using namespace std; int a[10004]; int dp[10004][105]; int mark[10004][105]; bool cmp(int x,int y) { return x>y; } int main() { int n,m; scanf("%d %d",&n,&m); memset(dp,0,sizeof(dp)); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); } sort(a+1,a+n+1,cmp); for(int i=1;i<=n;i++) { for(int j=m;j>=a[i];j--) { int tmp=dp[i-1][j-a[i]]+a[i]; if(dp[i-1][j]>tmp) { dp[i][j]=dp[i-1][j]; } else { dp[i][j]=tmp; mark[i][j]=1; } } } if(dp[n][m]!=m) { printf("No Solution"); } else { vector<int> v; while(m) { while(!mark[n][m]) { n--; } v.push_back(a[n]); m-=a[n]; n--; } int i; for(i=0;i<v.size()-1;i++) { printf("%d ",v[i]); } printf("%d",v[i]); } }