poj3616 Milking Time(简单dp——区间最大调度问题)

题意:牛在n时间内产奶,农夫有m段时间可以挤奶,每一段时间有开始点strat,结束点end,和这段时间的挤奶量w。 每一次挤奶后,牛都必须休息r时间。问在最合理的挤奶安排下挤到的最大牛奶量是多少?

思路:咋一看和用贪心方法求解的最多区间问题有点类似,然后仔细一看又发现不一样。这题是最大区间问题。
推荐一下这篇博客

下面摘取一些重要内容:
1.最多区间问题可以通过贪心算法求解,贪心策略是:在可选的工作中,每次都选取结束时间最早的工作。

2.最多区间问题也可以使用dp来求解。假设区间已经排序,可以尝试这样设计递归式:前i个区间的最多不重叠区间个数为dp[i]。dp[i]等于啥呢?我们需要根据第i个区间是否选择这两种情况来考虑。如果我们选择第i个区间,它可能和前面的区间重叠,我们需要找到不重叠的位置k,然后计算最多不重叠区间个数dp[k]+1(如果区间按照开始时间排序,则前i+1个区间没有明确的分界线,我们必须按照结束时间排序);如果我们不选择第i个区间,我们需要从前i-1个结果中选择一个最大的dp[j];最后选择dp[k]+1和dp[j]中较大的。

3.最大区间调度问题则是直接利用上面提到的动态规划算法:首先按照结束时间排序区间,然后按照第i个区间选择与否进行动态规划。

这里dp[i]表示以第i个时间段为结尾的最大长度。需要注意的是dp[i]必须要选择第i个时间段,所以这就导致了最后的dp[m]并不一定是最优解,需要最后遍历全部的dp数组才能知道最优解是多少。
然后这题的思想和lis其实是有点类似的。

#include <algorithm>
#include <iostream>
#include <cstdio>
using namespace std;
const int maxn = 1005;
struct node {
    int st, ed, val;
}  e[maxn];
bool cmp(node a, node b) {
    return a.st < b.st;//按结束时间和开始时间排序无影响,不知道原因,可能是题目数据太弱了,一般按照结束时间
    //return a.ed<b.ed;
}
int n, m, r;
int dp[maxn];
int main() {
    scanf("%d%d%d", & n, &m, &r);
    for(int i = 1; i <= m; i++) {
        scanf("%d%d%d", &e[i].st, &e[i].ed, &e[i].val);
        e[i].ed += r;
    }
    sort(e + 1, e + 1 + m, cmp);
    int ans = 0;
    for(int i = 1; i <= m; i++) {
        dp[i] = e[i].val;//以第i个区间为结尾
        ans = max(ans, dp[i]);
        for(int j = 1; j < i; j++) {
            if(e[j].ed <= e[i].st ) {
                dp[i] = max(dp[i], dp[j] + e[i].val);
                ans = max(ans, dp[i]);
            }
        }

    }
    printf("%d\n", ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/yiqzq/article/details/80358289