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

相關日誌