标签:
看上去非常像背包的问题,但是体积太大了。
线性规划的知识,枚举附近点就行了,优先选性价比高的,
宝物有两种体积为S0,价值V0,体积S1,价值V1。
枚举分以下几种:
1:枚举拿宝物1的数量,然后尽量多拿宝物2;O(N/S0)
2:枚举拿宝物2的数量,同上;O(N/S1)
3.贪心,尽量选性价比高的
令gcd(S0,S1)= t,S1/t*S0 = S0/t*S1;体积相同的情况下尽量选价值高的,如果S1*V0>S0*V1大,那么枚举拿宝物2的数量,最多S0/t-1个否则一定可以换成S1/t个宝物1。反之亦然。O(max{S0/t,S1/t})
提前判断选择枚举量最小的即可。
#include<bits/stdc++.h> using namespace std; typedef long long ll; ll GCD(ll a,ll b){ return b?GCD(b,a%b):a; } int main() { // freopen("in.txt","r",stdin); int T; ll S[2]; ll V[2]; ll n; scanf("%d",&T); for(int cas = 1; cas <= T; cas++){ scanf("%lld%lld%lld%lld%lld",&n,S,V,S+1,V+1); bool flag0 = S[1]*V[0] > S[0]*V[1]; ll gcd = GCD(S[1],S[0]); ll t = (flag0? S[0]/gcd : S[1]/gcd )-1; ll a[3] = {n/S[0],n/S[1],t}; ll Value = 0; int flag = min_element(a,a+3)-a; int M = t; if(flag <= 1) { if(flag == 1) {swap(*S,S[1]); swap(*V,V[1]); M = a[1];} else M = *a; }else if(flag0) {swap(*S,S[1]); swap(*V,V[1]);} //枚举拿宝物0的数量 for(int i = 0; i <= M; i++){ int j = (n-S[0]*i)/S[1]; ll val = i*V[0] + j*V[1]; Value = max(Value,val); } printf("Case #%d: %lld\n",cas,Value); } return 0; }
UVA 12325 Zombie'sTreasureChest
标签:
原文地址:http://www.cnblogs.com/jerryRey/p/4637101.html