大意是: 一些战士来到了一个村庄,发现了两种宝石和一个宝箱,每种宝石的个数是无限的,给出了宝箱的大小 N 和两种宝石的 size 和 value ,即 N s1 v1 s2 v2,已知这五个两,求利用这个宝箱,战士能够带走多大价值的宝石。 五个数的范围是 int 。 也就是 10^9。
如果范围比较小的话,就直接可以用多重背包的解法。 但是数据范围是 10^9 就没法用 多重背包来做了。。
在这给出一种数学的解法,非背包的解法。
解:1 。求出 s1,s2 的最小公倍数。最小公倍数等于s1乘以s2 在除以s1和s2在最大公约数即lcm=(s1*s2)/gcd(s1,s2)。
为什么求最小公倍数呢?
会有这么一个性质存在。。a = lcm /s1,b = lcm/s2 。 最小公倍数除以s1 s2 后的到 a,b。 a 个宝石一 和 b 个宝石二 所占的空间是相同的。
于是对于最优解中,单位价值小的宝石取得个数应该小于最大公倍数除以这个宝石体积。也就是说 如果宝石一的单位价值小的话, 那么num1 < a。
证明。设num1>a,那么对于这num1 个宝石 从中取出a个 ,把这a 个换成b个宝石二。由于a个宝石一 跟b个宝石二的所占的体积相同,但宝石二的单位价值更大。所以更换以后的总价值会更大,则num1 的个数应该小于a。
2 。因此我们可以把N 划分成两部分来求 1。intvn = N%lcm +2*lcm。(其实N%lcm +lcm 就够了但不会证明就用了N%lcm+2*lcm了。最效率影响不大) 2。N-vn 这两部分。 对部分二 一定是lcm 的倍数 直接能够求出这部分的最优解。关键是部分一。 为什么划分出部分1呢? 我们可以单独考虑宝石一小于a 的部分和宝石二小于b的部分。vn 定能覆盖这两部分的体积。
对于vn 这暴力求解。 for from 0 to vn/(max(s1,s2)) 循环大的值,是因为循环次数少,提高效率。这个循环最坏情况大致是10^4 到10^5 。
两部分总价值的就是解。。
(表达不好。。。。。。。。)
#include <iostream> #include <cstdio> #include <cstring> #define LL long long using namespace std; int t; int n,s1,v1,s2,v2; // 求最大公约数 int gcd(int da,int xiao){ int temp =0; while(xiao!=0){ temp = da%xiao; da =xiao; xiao = temp; } return da; } int max(int a,int b){ return (a>b)?a:b; } // LL 在 define 是long long LL max2(LL a,LL b){ return (a>b)?a:b; } int min(int a,int b){ return (a<b)?a:b; } LL cal (){ LL sum = n; //answer 为 最大价值 最后返回这个answer LL answer = 0; //a 为 s1 s2 中的大值,va 为 a 的value int a = max(s1,s2); int b = min(s1,s2); int va,vb; if(s1==a){ va = v1; vb = v2; }else{ va = v2; vb = v1; } // 求最小公倍数 。。 返回值 longlong 否则 wa 我一开始就wa 在这 LL lcm = s2/gcd(a,b)*(LL)s1; if(sum>=2*lcm){ int num = (sum-2*lcm)/lcm; answer += num*max2(lcm/s1*v1,lcm/s2*v2); sum =sum - num*lcm; } int i_max = sum/a; LL maxn=0; //循环暴力求解 for(int i=0 ;i<=i_max;i++){ int j = (sum-i*a)/b; LL tmp = i*(LL)va+j*(LL)vb; maxn=max2(maxn,tmp); } answer += maxn; return answer; } int main(){ scanf("%d",&t); for(int i=1;i<=t;i++){ scanf("%d%d%d%d%d",&n,&s1,&v1,&s2,&v2); printf("Case #%d: ",i); cout << cal()<<endl; } }
这个题目一定要注意 long long 的范围 。。。。。
这个题目某些情况可以特判后提高效率 。比如正好整除的情况 。。。
此题还有其他解法,稍后附上。