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

[文章目录]

Description

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

发现一个性质:假设位置[i,j]都没有交作业的话,无论我交的顺序怎样,总会有一次我交了一端,之后交另一端的作业,这个过程中完全可以把之前已经交的作业交上去,所以说下一个领的作业一定是i位置或是j位置的作业。
设f[i][j]表示我当前在i位置,i~j位置都没有领的最短时间(i< j),那么即可转移到f[i+1][j]和f[j][i+1]。i>j同理。每次计算路程时间并和时间取最大值。
统计答案的时候枚举f[i][i],计算领i的时间和i走到出口的时间更新答案。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int inf=0x3f3f3f3f;
int c,n,pos;
int f[1010][1010],T[1010];
inline int Abs(int x){return x>0?x:-x;}
int main()
{
    scanf("%d%d%d",&c,&n,&pos);
    int x,y,L=n,R=0;
    for(int i=1;i<=c;++i)
    {
        scanf("%d%d",&x,&y);
        T[x]=max(T[x],y); if(T[x]!=0) L=min(L,x),R=max(R,x);
    }
    memset(f,0x3f,sizeof f);
    for(int i=R;i<=n;++i) f[0][i]=0;
    for(int i=R;i<=n;++i) for(int j=0;j<=L;++j) f[i][j]=i;
    for(int i=n;i>=1;--i)
    {
        for(int j=0;j+i<=n;++j)
        {
            f[j+1][j+i]=min(f[j+1][j+i],max(T[j],f[j][j+i])+1);
            f[j+i-1][j]=min(f[j+i-1][j],max(T[j+i],f[j][j+i]+i)+1);
        }
        for(int j=n;j-i>=0;--j)
        {
            f[j-1][j-i]=min(f[j-1][j-i],max(T[j],f[j][j-i])+1);
            f[j-i+1][j]=min(f[j-i+1][j],max(T[j-i],f[j][j-i]+i)+1);
        }
    }
    int ans=inf;
    for(int i=0;i<=n;++i) ans=min(ans,max(f[i][i],T[i])+Abs(i-pos));
    printf("%d",ans); return 0;
}

发表评论

邮箱地址不会被公开。 必填项已用*标注