一中OJ #3514 礼物 | 暴搜 + 剪枝 | 解题报告

一中OJ | #3514 礼物

时限 1000MS/Case 内存 128MB/Case





题目描述

你有一个体积为N的箱子和两种数量无限的宝物。宝物1的体积为S1,价值为V1,宝物2的体积为S2,价值为V2。你的任务是计算箱子最多能装多大价值的宝物。注意每种宝物都必须拿非负整数个。

输入格式

多组数据,每组数据占一行,包含五个整数:N,S1,V1,S2,V2,他们的意义如题目描述。

输出格式

每组数据输出一行,表示箱子能装入的宝物的最大价值。

样例输入

100 1 1 2 2
100 34 34 5 3 

样例输出

100

86

数据范围

N,S1,V1,S2,V2均为32位带符号整数。
最多不超过100组数据。

----------------------------------------------------------

题目分析

枚举题,需要将时间复杂度降到o(sqrt(n))比较好过

所以将每组数据划分四种情况

1.当S1 == S2

这种很简单就不用说了

2.当S1 >= sqrt(n) 且 S1 >= S2

枚举S1的个数,算最大的ans

3.当S2 >= sqrt(n) 且 S2 >= S1

同(2.),枚举S2的个数,算最大的ans

4.当S1 < sqrt(n) 且 S2 < sqrt(n)

以S1*S2为一个单位,假设选择S2个物品1,S1个物品2,那么总体积都是S1*S2,选择物品1的价值就是S2*V1,物品2是S1*V2。这样就可以最优化选择一种物品。剩下的部分重复(2.)(3.)步骤即可

----------------------------------------------------------

代码

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <set>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#define hashsize 1000003
#define inf 0x7f7f7f7f
using namespace std;
int main()
{
//	freopen("Outp.txt","w+",stdout);
	long long n,s1,s2,v1,v2;
	while(cin>>n>>s1>>v1>>s2>>v2)
	{
		if(s1==s2)
		{
			cout<<(long long)(n/s1)*max(v1,v2)<<endl;
			continue;
		}
		long long c1=0,c2=0,ans=0,subb=0;
		if(s1>s2 && s1*s1>=n) //当s1比较大 
		{
			for(c1=0;c1*s1<=n;c1++)
			{
				ans=max(ans,(long long)c1*v1+(n-c1*s1)/s2*v2);
			}
		}
		else if(s2>s1 && s2*s2>=n) //当s2比较大 
		{
			for(c2=0;c2*s2<=n;c2++)
			{
				ans=max(ans,(long long)c2*v2+(n-c2*s2)/s1*v1);
			}
		}
		else
		{
			if(s1*v2>s2*v1) //取物品2更划算
			{
				ans=(n/(s1*s2))*s1*v2; //先取尽量多的物品2
				n=n%(s1*s2);
				if(s1>s2 && s1*s1>=n) //当s1比较大 
				{
					for(c1=0;c1*s1<=n;c1++)
					{
						subb=max(subb,c1*v1+(n-c1*s1)/s2*v2);
					}
				}
				else if(s2>s1 && s2*s2>=n) //当s2比较大 
				{
					for(c2=0;c2*s2<=n;c2++)
					{
						subb=max(subb,c2*v2+(n-c2*s2)/s1*v1);
					}
				}
				ans+=subb;
			}
			else //取物品1更划算 
			{
				ans=(n/(s1*s2))*s2*v1;
				n=n%(s1*s2);
				if(s1>s2 && s1*s1>=n) //当s1比较大 
				{
					for(c1=0;c1*s1<=n;c1++)
					{
						subb=max(subb,c1*v1+(n-c1*s1)/s2*v2);
					}
				}
				else if(s2>s1 && s2*s2>=n) //当s2比较大 
				{
					for(c2=0;c2*s2<=n;c2++)
					{
						subb=max(subb,c2*v2+(n-c2*s2)/s1*v1);
					}
				}
				ans+=subb;
			}
		}
		cout<<ans<<endl;
	}
	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值