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;
}

 

posted @ 2011-11-30 14:52  枕边梦  阅读(506)  评论(0编辑  收藏  举报