UVA 12325 Zombie'sTreasureChest 宝箱 (奇怪的暴力,分类枚举)

看上去非常像背包的问题,但是体积太大了。

线性规划的知识,枚举附近点就行了,优先选性价比高的,

宝物有两种体积为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)