您的位置:首页 > 其它

hdu 2639 第k大01背包

2015-03-19 13:04 120 查看
求每个状态里的k优解,然后合并

/*
HDU  2639
求01背包的第k大解。
合并两个有序序列
*/

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
const int MAXN=110;
int dp[1010][50];//dp[i][j]表示容量为i,第j大的值
int value[MAXN];
int weight[MAXN];

int a[50];
int b[50];

int N,V,K;

void DP()
{
memset(dp,0,sizeof(dp));
for(int i=0;i<N;i++)
for(int j=V;j>=value[i];j--)
{
for(int k=1;k<=K;k++)
{
a[k]=dp[j][k];
b[k]=dp[j-value[i]][k]+weight[i];
}
int x,y,z;
x=y=z=1;
a[K+1]=b[K+1]=-1;//这个一定要
while(z<=K&&(x<=K||y<=K))//合并两个已经排好序的序列
{
if(a[x]>b[y])dp[j][z]=a[x++];//注意相同的只算一个
else dp[j][z]=b[y++];
if(dp[j][z]!=dp[j][z-1])z++;
}
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d%d",&N,&V,&K);
for(int i=0;i<N;i++)scanf("%d",&weight[i]);
for(int i=0;i<N;i++)scanf("%d",&value[i]);
DP();
printf("%d\n",dp[V][K]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: