HDU 4600

模拟加贪心

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
const int maxn = 1111;
struct node {
    int area, num, income, next_ripe;
    node(int area = 0, int num = 0, int income = 0, int next_ripe = 0) :
            area(area), num(num), income(income), next_ripe(next_ripe) {
    }
} f[10];
int Q[maxn], P[maxn], N[maxn], M[maxn];
int NUM[10], cnt[10], area[10];

LL go(int money, int D, int Q, int P, int period) {
    int j, day = 0, more;
    LL have = money, income;

    while (day <= D) {
        if (day + period > D)
            break;
        income = 0;
        for (j = 0; j < 5; ++j) {
            if (f[j].income <= Q)
                continue;
            more = have / Q;
            more = min(more, NUM[j]);
            have -= 1LL * Q * more;
            income += 1LL * P * more * f[j].area;
        }
        have += income;
        day += period;
    }
    return have;
}

LL go(int money, int D, int Q, int P, int N, int M) {
    int j, day = 0, delta = 0, more;
    LL income;
    LL have = money;
    int remain[10];
    LL tmp = 0;
    copy(NUM, NUM + 10, remain);
    vector<node> v;
    vector<node>::iterator it;
    int cultivate = 0;
    while (day <= D) {
        income = 0;
        LL now = have;
        for (j = 0; j < 5; ++j) {
            more = now / Q;
            more = min(more, remain[j]);

            if (more > 0 && day + N <= D) {
                LL harvest_times = (D - day - N) / M + 1;
                if (harvest_times * P * area[j] > Q) {

                    v.push_back(node(area[j], more, f[j].income, N));
                    now -= 1LL * Q * more;
                    cultivate += more;
                    remain[j] -= more;
                }
            }
        }
        delta = 44444444;
        for (it = v.begin(); it != v.end(); ++it)
            delta = min(delta, it->next_ripe);
        if (day + delta > D)
            break;

        day += delta;
        income = 0;
        for (it = v.begin(); it != v.end(); ++it) {
            it->next_ripe -= delta;
            if (it->next_ripe == 0) {
                income += 1LL * it->income * it->num;
                it->next_ripe = M;
            }
        }
        tmp += income;
        have = now + income;
    }
    return have;
}

int main() {
    int w, h, A, D, Y, i, a, b, j;
    int T;
    scanf("%d", &T);
    while (T--) {
        scanf("%d %d %d %d %d", &w, &h, &A, &D, &Y);

        a = w % 3, b = h % 3;

        NUM[0] = (w / 3) * (h / 3);
        NUM[1] = 1;
        NUM[2] = h / 3 - 1;
        NUM[3] = w / 3 - 1;
        NUM[4] = 2;

        area[0] = 9;
        area[1] = 3 * (a + b) - a * b;
        area[2] = a * 3;
        area[3] = b * 3;
        area[4] = a * b;

        if (a < b) {
            swap(NUM[2], NUM[3]);
            swap(a, b);
            swap(area[2], area[3]);
        }

        LL ans = Y;
        for (i = 0; i < A; ++i) {

            scanf("%d%d%d%d", Q + i, P + i, N + i, M + i);

            for (j = 0; j < 5; ++j) {
                f[j] = node(area[j], 0, P[i] * area[j], N[i]);
            }
            if (!M[i])
                ans = max(ans, go(Y, D, Q[i], P[i], N[i]));
            else
                ans = max(ans, go(Y, D, Q[i], P[i], N[i], M[i]));
        }
        printf("%I64d\n", ans);
    }
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值