hdu 2639 Bone Collector II (背包问题 第K优解)
与一般的背包问题不同,要求的是第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;
}

浙公网安备 33010602011771号