与一般的背包问题不同,要求的是第K优解,首先,我们要搞清楚的一个问题就是最优解是怎么求出来的。
对于求最优解的情况,我们对每一种状态只保存了该状态下的最优解,忽略了其他解,进而实现状态之间的转移,而对于求第K优解的情况呢?其实只需要保存每一种状态下的前K优解,从这K个状态进行状态间的转移,同时去重,保存当前状态的K优解即可。
#include<iostream> #include<algorithm> #include<set> using namespace std; int v[101],w[101]; int n,m,k,dp[1010][31]; int tmp[65]; bool cmp(int a,int b) { return a>b; } int main() { int cas; scanf("%d",&cas); while(cas--) { scanf("%d %d %d",&n,&m,&k); for(int i=0;i<n;i++) scanf("%d",&w[i]); for(int i=0;i<n;i++) scanf("%d",&v[i]); memset(dp,0,sizeof(dp)); for(int i=0;i<n;i++) { for(int j=m;j>=v[i];j--) { int temp=0; for(int t=0;t<k;t++) { tmp[temp++]=dp[j][t]; tmp[temp++]=dp[j-v[i]][t]+w[i]; } //tmp数组保存该状态的所有可能解,再去重,求出k优解 sort(tmp,tmp+k*2,cmp); temp=1; dp[j][0]=tmp[0]; for(int t=1;t<k*2 && temp<k;t++) { if(tmp[t]!=tmp[t-1]) dp[j][temp++]=tmp[t]; } } } printf("%d\n",dp[m][k-1]); } return 0; }