[题解]luogu_P2577午餐(贪心dp

首先第一反应该是贪心,对于同一队列中的人应该是吃时间长的人先打饭更优,因为打饭时间不可避免,同时吃饭的人更多就一定更优,接下来就是处理谁在哪队了,设$f[i][j][k]$为前i人队1花费j时间队2花费k时间全部吃完用的最小时间,然而其实不用因为j+k为全集,所以搞个前缀和可以减一维,

转移为$f[i][j]=min(f[i][j],max(f[i-1][j-a[i].a], j+a[i].b),max(f[i-1][j], sum[i]-j+a[i].b))$,

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=209;
int n;
int f[maxn][maxn*maxn],sum[maxn];
struct node{
    int a,b;
    bool operator <(const node&t)const{
        return b>t.b||(b==t.b&&a<t.a);
    }
}a[maxn];
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d%d",&a[i].a,&a[i].b),sum[i]=sum[i-1]+a[i].a;
    sort(a+1,a+1+n);
    memset(f,0x3f,sizeof(f));
    f[0][0]=0;
    for(int i=1;i<=n;i++)
    for(int j=0;j<=sum[i];j++){
        if(j>=a[i].a)f[i][j]=min(f[i][j],max(f[i-1][j-a[i].a],j+a[i].b));
        f[i][j]=min(f[i][j],max(f[i-1][j],sum[i]-j+a[i].b));
    }
    int ans=1e9;
    for(int i=0;i<=sum[n];i++)
    ans=min(ans,f[n][i]);
    printf("%d
",ans);
}
原文地址:https://www.cnblogs.com/superminivan/p/11671476.html