1002 Business

要解这道题目,感觉最关键的因素就是找到第 i 件任务最晚开始的时间 K_i。这个看似简单,但是对建模的功底要求相当高。我一开始就把 K_i 当成了 j-L_i ,但其实不是的。后者就相当于把第 i 件任务锁死在最后面完成,但其实是允许放在之前完成的,只要还满足截止日期即可,所以应当在 D_i 和当前的 j 之间选取一个较小值再减去 L_i 获得 K_i 才是转移过程中当选择第 i 个任务时的上一个状态。

#include<iostream>
#include<vector>
#include<algorithm>
#include<cmath>
using namespace std;

struct Node {
    int p, l, d;
};

int main() {
    int n;
    cin >> n;
    vector<Node> arr(n + 1);
    for (int i = 1; i <= n; i++) {
        cin >> arr[i].p >> arr[i].l >> arr[i].d;
    }
    sort(arr.begin(), arr.end(), [](const Node &a, const Node &b) {
        return a.d < b.d;
    });
    int t = arr.back().d;
    vector<vector<int>> dp(n + 1, vector<int>(t + 1));
    for (int i = 1; i <= n; i++) { // 第i件物品
        for (int j = 1; j <= t; j++) { // 前j天
            int k = min(arr[i].d, j) - arr[i].l; // 第i件任务最晚开始的时间
            dp[i][j] = dp[i - 1][j]; // 默认不选第i件
            if (k >= 0) {
                dp[i][j] = max(dp[i][j], dp[i - 1][k] + arr[i].p); // 注意体会这里k的含义,为什么不是j没有涵盖所有的情况
            }
        }
    }
    cout << dp[n][t] << endl;

    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值