BZOJ 3379: [Usaco2004 Open]Turning in Homework 交作业

Description

    贝茜有C(1≤C≤1000)门科目的作业要上交,之后她要去坐巴士和奶牛同学回家.
每门科目的老师所在的教室排列在一条长为H(1≤H≤1000)的走廊上,他们只在课后接收作业.交作业不需要时间.贝茜现在在位置0,她会告诉你每个教室所在的位置,以及走廊出口的位置.她每走1个单位的路程,就要用1秒.她希望你计算最快多久以后她能交完作业并到达出口.

Input

 第1行输入三个整数C,H,B,B是出口的位置.之后C行每行输入两个整数,分别表示一个老师所在的教室和他的下课时间.

Output

 
    贝茜最早能够到达出口的时间.

Sample Input

4 10 3
8 9
4 21
3 16
8 12

Sample Output

22

 

 

 

解法:一个经典的DP。令dp[i][j][0/1] 表示除了i~j这段区间没完成其他的都完成了,然后现在要完成i(0)或j(1)的最短时间。这样子就是从一个大区间F[1][n] 推到F[i][i] ,最后我们就能比较从哪个位置前往终点最优了。
转移方程跟第一种想法差不多,只不过第一种想法是用小区间推大区间,所以会导致答案不能保证最优。

 

#include <bits/stdc++.h>
using namespace std;
int C, H, B;
int dp[1005][1005][2];
struct node{
    int x, t;
    bool operator<(const node &rhs)const{
        return x<rhs.x;
    }
}A[1005];

int main()
{
    scanf("%d %d %d", &C,&H,&B);
    for(int i=1; i<=C; i++){
        scanf("%d %d", &A[i].x, &A[i].t);
    }
    sort(A+1,A+C+1);
    memset(dp, 0x7f, sizeof(dp));
    dp[1][C][0] = max(A[1].x, A[1].t);
    dp[1][C][1] = max(A[C].x, A[C].t);
    for(int i=1; i<=C; i++){
        for(int j=C; j>=1; j--){
            dp[i][j][0] = min(dp[i][j][0], max(dp[i-1][j][0]+A[i].x-A[i-1].x, A[i].t));
            dp[i][j][0] = min(dp[i][j][0], max(dp[i][j+1][1]+A[j+1].x-A[i].x, A[i].t));

            dp[i][j][1] = min(dp[i][j][1], max(dp[i-1][j][0]+A[j].x-A[i-1].x, A[j].t));
            dp[i][j][1] = min(dp[i][j][1], max(dp[i][j+1][1]+A[j+1].x-A[j].x, A[j].t));
        }
    }
    int ans = INT_MAX;
    for(int i=1; i<=C; i++){
        ans = min(ans, min(dp[i][i][0], dp[i][i][1])+abs(B-A[i].x));
    }
    printf("%d\n", ans);
    return 0;
}

 

posted @ 2017-09-09 19:39  zxycoder  阅读(...)  评论(...编辑  收藏