HDU_4091_Zombie’s Treasure Chest_最小公倍数、机智地枚举

针对超大背包问题,本文提出了一种高效的优化算法。通过计算两种物品的最小公倍数来简化问题规模,并结合暴力枚举策略求解剩余部分,实现了快速准确地找到最大价值方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

被队友卖了去给集训队买车票再见


题意:

超大背包,有两种物品,大小分别为s1,s2,价值分别为v1,v2,背包容积为n,问最大获取价值



Input
  There are multiple test cases. The number of test cases T (T <= 200) is given in the first line of the input file. For each test case, there is only one line containing five integers N, S1, V1, S2, V2, denoting the size of the treasure chest is N and the size and value of an emerald is S1 and V1, size and value of a sapphire is S2, V2. All integers are positive and fit in 32-bit signed integers.
 

Output
  For each test case, output a single line containing the case number and the maximum total value of all items that the warriors can carry with the chest.


背包DP果断不行,数据太大了,还是康康机智,想出了优化办法。

先找出s1,s2的最小公倍数m,占用m空间时的最优解是确定的,要么全装第一个物品,要么全装第二个物品,n/m*m的空间都用这种方法完成,剩下的空间暴力枚举即可。

最小公倍数很快,算结果O(1)即可。剩余空间小于m,存在关系sqrt(m)<min(max(s1,s2),sqrt(10^9)),遍历需要m/max(s1,s2)次操作,小于min( max(s1,s2), sqrt(10^9) ),所以肯定可以快速解决。


代码如下:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
#define LL long long
LL max( LL a, LL b ){
	if( a >= b )
		return a;
	else return b;
} 
LL gcd( LL a, LL b ){
	return b == 0 ? a : gcd( b, a % b );
}
LL lcm( LL a, LL b ){
	return a / gcd( a, b ) * b;
}
int main(){
	int t;
	int ss = 0;
	scanf("%d",&t);
	while( t-- ){
		long long v, s1, s2, v1, v2;
		printf("Case #%d: ",++ss);
		scanf("%I64d%I64d%I64d%I64d%I64d",&v,&s1,&v1,&s2,&v2);
		if( s1 < s2 ){
			int tmp=s1;
			s1=s2;
			s2=tmp;
			tmp=v1;
			v1=v2;
			v2=tmp;
		}
		long long L = lcm( s1, s2 );
		long long c = v % L;
		if(  L > v ){
			LL ans = 0;
			for( long long i = 0; i <= c / s1; ++i ){
				ans = max( ans, i * v1 + ( c - s1 * i ) / s2 * v2 );
			}
			printf("%I64d\n",ans);
		}
		else{
			LL ans = 0;
			for( long long i = 0; i <= (c + L) / s1; ++i ){
				ans = max( ans,  i * v1 + (  c + L - s1 * i ) / s2 * v2 );
			}
			ans += ( v - L ) /  L * max( L / s1 * v1, L / s2 * v2 );
			printf("%I64d\n",ans);
		}
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值