HDU2191

题目

见HDU2191(其实就是一道多重背包

Input

输入数据首先包含一个正整数C,表示有C组测试用例,每组测试用例的第一行是两个整数n和m(1<=n<=100, 1<=m<=100),分别表示经费的金额和大米的种类,然后是m行数据,每行包含3个数p,h和c(1<=p<=20,1<=h<=200,1<=c<=20),分别表示每袋的价格、每袋的重量以及对应种类大米的袋数。

Output

对于每组测试数据,请输出能够购买大米的最多重量,你可以假设经费买不光所有的大米,并且经费你可以不用完。每个实例的输出占一行。

Sample Input

1
8 2
2 100 4
4 100 2

Sample Output

400

思路


对于每一个物品,我们枚举其剩余类,具体来说,就是把一个容量为j的背包在只考虑该物品情况下,能够按从哪些部分转移过来,也就是候选集合,举例来说,如果j=5,该物品(质量W,价值V,件数C)W=2,那么余数为1的类有2,4
所以,我们一重枚举物品,一重枚举余数,然后一重枚举件数,没错,每一次枚举余数都需要单调队列,但是它的时间复杂度依然为O(nm)
code:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<deque>
#include<cstdio>
#include<map>
using namespace std;
deque<int> a;
int a2[1001];
int c2[1001],mx,t,v,w,c,b,k;
int n,p,q,i,m;
void read(int& x)
{
	x=0;
	int f=1;
	char ch=getchar();
	while (!isdigit(ch)) (ch=='-')&&(f=-1),ch=getchar();
	while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
	x*=f;
}
void wr(int x)
{
	(x<0)&&(x=-x,putchar('-'));
	if (x>9) wr(x/10);
	putchar(x%10^48);
}
int main()
{
	read(t);
	while (t--)
	{
		read(m),read(n);
		memset(a2,0,sizeof(a2));
		for (i=1;i<=n;i++)
		{
			read(w),read(v),read(c);//v价值,w体积,c数量 
			for (b=0;b<w;b++)
			{
				int mxp=(m-p)/w;//最大件数 
				for (k=mxp-1;k>=max(mxp-c,0);k--)//买mxp件的候选集合 
				{
					while (a.size()&&a2[a.back()*w+b]-a.back()*v<=a2[k*w+b]-k*v) a.pop_back();
					a.push_back(k);
				}
				for (int p=mxp;p>=0;p--)//枚举购买件数
				{
					if (a.size()&&a.front()>p-1) a.pop_front();
					if (a.size())
					{
						a2[p*w+b]=max(a2[a.front()*w+b]+v*(p-a.front()),a2[p*w+b]);
					}
					if (p-c-1<0) continue;//下界超限 
					k=p-c-1;
					while (a.size()&&a2[a.back()*w+b]-a.back()*v<=a2[k*w+b]-k*v) a.pop_back();
					a.push_back(k);
				}
			}
		}
		wr(a2[m]);
		printf("\n");
	}
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值