G16 种苹果

最近流行种苹果的游戏,玩家种下一颗苹果树,初始成长值为0,每次浇水都会增加成长值,当成长值大于等于V时,就可以收获成熟的苹果了。玩家拥有五种颜色(红色、黄色、蓝色、绿色、紫色)的水壶若干个,每浇水一次就消耗一个水壶,不同颜色的水壶水量不一定一样,因此用不同颜色的水壶浇水苹果树获得的成长值也可能不一样。苹果成熟后剩余水壶中的水量仍然可以继续在下一局游戏中继续使用,因此,玩家想用最少的水量让苹果成熟,最大程度节约水量。请你帮他计算下苹果成熟的最少浇水量。

输入格式:

输入第一行为一个整数T(1<=T<=100),代表测试数据的组数,每组数据的第一行为一个整数V(0<=V<=10^12),代表苹果成熟应达到的成长值,随后5行,每行包括三个整数N,G,W(0<=N<=1000,0<=W,G<=10^9),分别代表其中一种颜色水壶的个数,浇水后对应的成长值,水量,中间用空格分割,并且所有颜色水壶的总个数不超过1000。

输出格式:

每组数据都对应一行输出。如果苹果能够成熟,该行输出两个整数,分别代表苹果成熟时的最低浇水量和所获得的成长值。如果所有水壶的水量都浇上,苹果也成熟不了,则输出”Impossible!”。

输入样例:

3
100
20 5 5
16 10 4
3 20 10
15 2 2
5 8 6
60
2 3 2
3 5 6
1 3 5
2 6 1
3 4 2
50
2 20 10
3 10 20
2 5 6
20 4 10
12 6 5


输出样例:

40 100

Impossible!

30 52

代码:


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
struct my {
    ll w, g;
    int num;
    double g_w;
    bool operator<(const my& t) { return g_w > t.g_w; }
}tr[5];
ll ans = 1e18, sum, res = 0, sres = 0;
double n[5];
void dfs(ll V, int u) {
    if (V <= 0) {
        if (ans > res) {
            ans = res;
            sum = sres;
        }
        return;
    }
    if (u == 4) {
        ll t = min((ll)tr[u].num, V / tr[u].g + 1);
        if (t * tr[u].g >= V) {
            if (ans > res + t * tr[u].w) {
                ans = res + t * tr[u].w;
                sum = sres + t * tr[u].g;
            }
        }
        return;
    }
    if (V % tr[u].g == 0 && V / tr[u].g <= tr[u].num) {
        if (ans > res + V / tr[u].g * tr[u].w) {
            ans = res + V / tr[u].g * tr[u].w;
            sum = sres + V;
        }
    }
    else {
        ll up = min((ll)tr[u].num, (ll)n[u] + 9), down = max(0ll, (ll)n[u] - 9);
        for (int i = down; i <= up; i++) {
            res += i * tr[u].w;
            sres += i * tr[u].g;
            dfs(V - i * tr[u].g, u + 1);
            res -= i * tr[u].w;
            sres -= i * tr[u].g;
        }
    }
}
void solve() {
    ans = 1e18, sum = 0, res = 0, sres = 0;
    ll Vt,V;
    scanf("%lld", &V);
    Vt = V;
    for(int i=0;i<5;i++) n[i]=0;
    for (int i = 0; i < 5; i++) { scanf("%d %lld %lld", &tr[i].num, &tr[i].g, &tr[i].w); tr[i].g_w = (double)tr[i].g / tr[i].w; } // 按性价比来排
    sort(tr, tr + 5);
    for (int i = 0; i < 5; i++) {
        if (!V) break;
        if (tr[i].g * tr[i].num >= V) 
        {        n[i] = (double)V / tr[i].g; //需要的瓶数
         V = 0;
        }
        else V -= tr[i].g * tr[i].num, n[i] = tr[i].num; 
    }
    dfs(Vt, 0);
    if (ans == 1e18) puts("Impossible!");
    else printf("%lld %lld\n", ans, sum);
}
int main() {
    int Case;
    cin >> Case;
    while (Case--) solve();
    return 0;
}

时间复杂度:O();

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值