HDU2639 - Bone Collector II(第k大01背包)

41 篇文章 0 订阅

题目链接: HDU2639

【题意】给定每个物品的价值和费用,求出在V费用下能获得的第k大的价值是多少

【分析】这是经典的第k大01背包,一开始天真的认为只要在原来01背包基础上增加一个额外的递减队列,然后每次出现新的价值时维护更新这个队列就可以求出第k大值,交上去直接WA,后来核对几组数据后发现01背包只记录最大的那个值,而过程中不会出现所有可以得到的价值(想得到这个应该只有枚举吧),然后只能增加一维记录前k大了。

【AC CODE】109ms

#include <cstdio>
#include <cstring>
#define MAXN 1002
#define MAXM 1002
#define MAXK 32
#define max(a,b) (a>b?a:b)
int v[MAXN],w[MAXN],dp[MAXM][MAXK],a[MAXK],b[MAXK],p;
/*dp[j][k]表示前i个物品背包容量为j时第k大价值;
a[],b[]分别记录选择当前物品和不选择当前物品时候的前k大价值,然后每次合并两个序列的前k大即可*/

int main()
{
#ifdef SHY
    freopen("e:\\1.txt","r",stdin);
#endif
	int t;
	scanf("%d%*c", &t);
	while(t--)
	{
		int n,m;
		scanf("%d %d %d%*c", &n, &m, &p);
		for(int i = 1; i <= n; i++)
			scanf("%d%*c", &v[i]);
		for(int i = 1; i <= n; i++)
			scanf("%d%*c", &w[i]);
		memset(dp,0,sizeof(dp));
		memset(a,0,sizeof(a));
		for(int i = 1; i <= n; i++)
		{
			for(int j = m; j >= w[i]; j--)
			{
				for(int k = 1; k <= p; k++)
				{
					a[k] = dp[j-w[i]][k]+v[i];
					b[k] = dp[j][k];
				}
				//合并
				int k = 1,p1 = 1,p2 = 1;
				while(k <= p && (p1 <= p || p2 <= p))
				{
					if(a[p1] > b[p2]) dp[j][k] = a[p1++];
					else dp[j][k] = b[p2++];
					if(dp[j][k] != dp[j][k-1]) k++;
				}
			}
		}
		printf("%d\n", dp[m][p]);
	}
	return 0;
}


 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值