题目链接:
http://codeforces.com/problemset/problem/526/C
题意:
给你一个容量为V的背包,有两种物品,每种都有无穷多个。
第一种物品的体积为v1,价值为w1
第一种物品的体积为v2,价值为w2
输入V,w1,w2,v1,v2.计算这个背包最多能放价值多少的物品。
数据范围:
V,w1,w2,v1,v2 都在1到10^9范围内。
题解:
如果按照完全背包的做法,用dp来做,复杂度O(nV),n为物品数量,这道题物品数量为2,但是背包容量V很大。dp会超时。
正确思路是:
分两种情况讨论:
1.如果 max(v1,v2)>=根号V。
假设v1>=根号V.那么这个背包全放物品1最多只能放根号V个。物品1可以放0到根号V个。我们只需要暴力枚举物品1的个数,就可以算出来物品2的个数,算出来背包所能放的最大价值。ans=max(i*w1,(V-i*v1)/v2*w2).时间复杂度O(根号V);
2.如果 max(v1,v2)<根号V。
我们假设w1/v1<w2/v2(实际不满足这个条件可以交换这两个物品),也就是物品2的性价比更高。
物品1体积为v1,物品2体积为v2。那么v2个物品1和v1个物品2的体积相等。因为物品2的性价比比物品1高,所以最优情况下物品1最多放v2个。因为v2个物品1换成v1个物品2体积没变,价值更高了。枚举物品1的个数就可以算出来背包能放得最大价值了。时间复杂度O(根号v2). v2<根号V
所以最坏的情况下复杂度是O(根号V).
代码
#include<algorithm>
#include <iostream>
#include<cstring>
#include <cstdio>
using namespace std;
typedef long long ll;
const int maxn=5e5+5;
int main(){
ll v,a1,b1,a2,b2;
cin>>v>>a1>>a2>>b1>>b2;
ll x=max(b1,b2);
if(x*x>=v){
if(b1<b2) swap(a1,a2),swap(b1,b2);
ll ans=0;
for(int i=0;i<=v/b1;i++){
ans=max(ans,i*a1+(v-i*b1)/b2*a2);
}
cout<<ans<<endl;
}else{
if(1.0*a1/b1>1.0*a2/b2){
swap(a1,a2),swap(b1,b2);
}
ll ans=0;
for(int i=0;i<b2;i++){
ans=max(ans,i*a1+(v-i*b1)/b2*a2);
}
cout<<ans<<endl;
}
return 0;
}