01背包输出字典序最小的最优解
#include<bits/stdc++.h> using namespace std; const int maxn=1000+10; int n,k,w[maxn],v[maxn],dp[maxn][maxn]={0}; //倒着循环输出最优解方便,不能用滚动数组 //最优解有多个就是因为也有可能dp[i][j]==dp[i+1][j-w[i]]+v[i]&&dp[i][j]=dp[i+1][j], // 即选不选都行,为了字典序最小,应该选,那么就从前往后能选就选就行了 //输出最优解也可以用gij 表示在ij时,i选不选,但是不确定保存了之后是不是字典序最小 int main() { cin>>n>>k; for(int i=1;i<=n;i++) cin>>w[i]>>v[i]; for(int i=n;i>=1;i--){ for(int j=1;j<=k;j++){ if(j>=w[i]) dp[i][j]=max(dp[i+1][j],dp[i+1][j-w[i]]+v[i]); else dp[i][j]=dp[i+1][j]; } } int i=1,j=k; while(i<=n){ //也有可能dp[i][j]==dp[i+1][j-w[i]]+v[i]&&dp[i][j]=dp[i+1][j],即选不选都行,为了字典序最小,应该选,所以不能if(!dp[i][j]=dp[i+1][j]) if(j>=w[i]&&dp[i][j]==dp[i+1][j-w[i]]+v[i]){ //不断判断当前点选没选 cout<<i<<" "; j=j-w[i]; } i++; } // cout<<dp[1][k]<<endl; return 0; }
01背包输出字典序最小的最优解