bzoj1899: [ZJOI2004]Lunch 午餐

题目

题解:

有一个贪心策略:吃饭时间越长的越早打饭
然后动规,f[i][j]表示前i-1个数,第一个队列恰好要j的时间的最晚集合时间
可以降维,把i去掉
初始化:f[0]=0,其余为正无穷
第一个窗口打饭:
f[j]=min(f[j],max(f[j-x],j+y)) (x<=j<=sum)
=>f[j+x]=min(f[j+x],max(f[j],j+x+y)) (0<=j<=sum-x)
第二个窗口打饭:
f[j]=max(f[j],sum-j+y)
ans=max(f[i])
注意,这里的sum指a[1].x+a[2].x+…+a[i].x,而标程中的sum是少一个a[i].x的,所以题解和标程的状态转移方程不同

标程:

#include<bits/stdc++.h>
using namespace std;
struct kk{
    int x,y;
}a[203];
int n,i,j,x,y,f[40003],ans,sum;
int cmp(kk x,kk y){
    return x.y>y.y;
}
int main(){
    cin>>n;
    for (i=1;i<=n;i++) scanf("%d%d",&a[i].x,&a[i].y);
    sort(a+1,a+n+1,cmp);
    memset(f,1,sizeof(f));
    ans=f[0];f[0]=0;
    for (i=1;i<=n;i++){
        x=a[i].x;y=a[i].y;
        for (j=sum;j>=0;j--){
            f[j+x]=min(f[j+x],max(f[j],j+x+y));
            f[j]=max(f[j],sum-j+x+y);
        }
        sum+=x;
    }
    for (i=1;i<=sum;i++) ans=min(ans,f[i]);
    cout<<ans;
}

猜你喜欢

转载自blog.csdn.net/xumingyang0/article/details/80072224