USACO NOV07 Silver Milking Time 挤奶时间

动态规划

由于奶牛每次挤奶后都要休息R小时,我们不妨把这R小时加到每个时间段的后面。每个时间段看成一个带权区间,我们要求的是不重叠区间的权值和的最大值。

O(N^2)的算法

首先对每个区间按照左端的位置升幂排序,然后进行动态规划。

状态设定

* F[i]为前i个区间,右端最大的区间为i时,所得到的最大值 

状态转移方程

* F[i]=Max{ F[k] } + W[i] (k=1..i-1 并且 right[k] <= left[i])
      o W[i]为区间i的价值
      o right[k]为区间k的右端
      o left[i]为区间i的左端 

边界条件

* F[0]=0 

目标结果

* Ans=Max{ F[i] } (i=1..M) 
#include <iostream>
#define MAX 1001
using namespace std;

typedef struct
{
    int left,right,value;
}extent;

int T,N,R,Ans;
int F[MAX];
extent E[MAX];

inline int cmp(const void *a,const void *b)
{
    return ((extent *)a)->left - ((extent *)b)->left;
}

void init()
{
    int i;
    freopen("milkprod.in","r",stdin);
    freopen("milkprod.out","w",stdout);
    cin >> T >> N >> R;
    T+=R;
    for (i=1;i<=N;i++)
    {
        scanf("%d%d%d",&E[i].left,&E[i].right,&E[i].value);
        E[i].right+=R;
    }
    qsort(E+1,N,sizeof(E[0]),cmp);
}

void dynamic()
{
    int i,j,max;
    for (i=1;i<=N;i++)
    {
        max=0;
        for (j=1;j<=i-1;j++)
            if (E[j].right<=E[i].left && F[j]>max)
                max=F[j];
        F[i]=max+E[i].value;
        if (F[i]>Ans)
            Ans=F[i];
    }
}

int main()
{
    init();
    dynamic();
    cout << Ans << endl;
    return 0;
}
<a href="http://www.ruvtex.cn/wiki/USACOMonthly/2007_11_S/Milking_Time/Chinese">挤奶时间</a>

译 By BYVoid

描述

贝茜是一只非常努力工作的奶牛,她总是专注于提高自己的产量。为了产更多的奶,她预计好了接下来的N (1 ≤ N ≤ 1,000,000)个小时,标记为0..N-1。

Farmer John 计划好了 M (1 ≤ M ≤ 1,000) 个可以挤奶的时间段。每个时间段有一个开始时间(0 ≤ 开始时间 ≤ N), 和一个结束时间 (开始时间 < 结束时间 ≤ N), 和一个产量 (1 ≤ 产量 ≤ 1,000,000) 表示可以从贝茜挤奶的数量。Farmer John 从分别从开始时间挤奶,到结束时间为止。每次挤奶必须使用整个时间段。

但即使是贝茜也有她的产量限制。每次挤奶以后,她必须休息 R (1 ≤ R ≤ N) 个小时才能下次挤奶。给定Farmer John 计划的时间段,请你算出在 N 个小时内,最大的挤奶的量。

输入

    * 第 1 行: 三个整数 N, M, R
    * 第 2..M+1 行: 第 i+1 行 每行三个整数,为 

输出

    * 第 1 行:一个整数 在 N 个小时内,最大的挤奶的量Farmer John放入挤奶计划,开始时间,结束时间,产量。 

样例输入

12 4 2
1 2 8
10 12 19
3 6 24
7 10 31

样例输出

43

相关日志