《3816: Zombie’s Treasure Chest》

好题!一开始看到题觉得和之前做过的很像,就三分然后wa了。

这题需要好好思考!考虑去枚举操作。

当某一种的最多可拿数量 <= 1e5时,我们可以直接枚举这一种取多少个。

当两种的最多可拿数量都 > 1e5时,这时很显然的是s1,s2都很小,那么我们的枚举范围需要压到和s1,s2线性相关,这样复杂度就比较低。

我们可以把这两个物品考虑成单位重量的物品,这样可以比较两者的性价比,即v1 / s2 与 v2 / s1的大小。

当v1 / s1 >= v2 / s2即 v1 * s2 >= v2 * s1时,此时,如果要放s1 个 v2 显然替换成s2 个 v1性价比更高,这里为什么性价比更高?

因为v1 * s2 >= v2 * s1,所以v2最多只会放置s1 - 1个,那么我们枚举v2的个数即可。

反之,v1最多只会放置s2 - 1个,那么枚举v1的个数即可。

输入会爆int,全都用longlong了。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int,int> pii;
const int N = 1e5+5;
const int M = 1e4+5;
const LL Mod = 1e9+7;
#define pi acos(-1)
#define INF 1e9
#define CT0 cin.tie(0),cout.tie(0)
#define IO ios::sync_with_stdio(false)
#define dbg(ax) cout << "now this num is " << ax << endl;
namespace FASTIO{
    inline LL read(){
        LL x = 0,f = 1;char c = getchar();
        while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}
        while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
        return x*f;
    }
}
using namespace FASTIO;

int main()
{
    int ca;ca = read();
    int lim = 100000;
    int tot = 0;
    while(ca--)
    {
        LL n,s1,v1,s2,v2;n = read(),s1 = read(),v1 = read(),s2 = read(),v2 = read();
        LL up1 = n / s1,up2 = n / s2;
        LL ans = 0;
        if(up1 <= lim)
        {
            for(LL i = 0;i <= up1;++i)
            {
                LL ma = 1LL * i * v1 + 1LL * (n - i * s1) / s2 * v2;
                ans = max(ans,ma);
            }
        }
        else if(up2 <= lim)
        {
            for(LL i = 0;i <= up2;++i)
            {
                LL ma = 1LL * i * v2 + 1LL * (n - i * s2) / s1 * v1;
                ans = max(ans,ma);
            }
        }
        else
        {
            LL tmp1 = s1 * v2,tmp2 = s2 * v1;
            if(tmp1 >= tmp2) 
            {
               for(LL i = 0;i < s2;++i)//v1最多s2 - 1
               {
                   ans = max(ans,i * v1 + (n - i * s1) / s2 * v2);
               }
            }
            else 
            {
                for(LL i = 0;i < s1;++i)//v2最多s1 - 1
                {
                    ans = max(ans,i * v2 + (n - i * s2) / s1 * v1);
                }
            }
        }
        printf("Case #%d: %lld\n",++tot,ans);
    }
    system("pause");
    return 0;
}
View Code

 

posted @ 2020-12-07 21:03  levill  阅读(73)  评论(0编辑  收藏  举报