先说说普通01包的状态问题吧
普通的01背包,在状态转移的过程中为了求出最优解,一定是遍历了所有的情况 然后再求的最优解。那么对于第k最优解问题,我们只需要再加一个维度,用来记录每一个状态k优解的状态就好了。
在普通背包过程中 每次的选举的状态为dp[i-1][j],dp[i-1][j-c[i]+w[i] 为了求解最优情况 我们一般是对这两个状态取最大值 然后依次遍历 得到最大值。那么,为了得到第k大的解,我们就需要另外使用数组来对两种状态的所有值记录下来 然后选取第k大的情况
上代码
#include<cstdio> #include<iostream> #include<string.h> using namespace std; int main() { int val[101],vol[101],dp[1001][33]; int aa[33],bb[33]; int n,v,k,t; cin>>t; while(t--) { cin>>n>>v>>k; for(int i=1;i<=n;i++) cin>>val[i]; for(int i=1;i<=n;i++) cin>>vol[i]; memset(dp,0,sizeof(dp)); for(int i=1;i<=n;i++) { for(int j=v;j>=vol[i];j--)//将 每次优化的k种解记录下来 { int z; for(z=1;z<=k;z++) { aa[z]=dp[j][z]; bb[z]=dp[j-vol[i]][z]+val[i]; } aa[z]=bb[z]=-1; int p,pp,ppp; p=pp=ppp=1; while(p<=k+1&&(aa[pp]!=-1||bb[ppp]!=-1))//加一个去重的过程 { if(aa[pp]>bb[ppp]) dp[j][p]=aa[pp++]; else dp[j][p]=bb[ppp++]; if(dp[j][p]!=dp[j][p-1]) p++; } } } cout<<dp[v][k]<<endl; } return 0; }
第k解的问题 让我对背包问题的最优化过程有了一个了解