LUOGU P2577 [ZJOI2005]午餐

传送门

解题思路

贪心+dp。首先一定是让吃的慢的先吃这是很显然的,所以按照b[i]排一遍序,然后考虑dp,设dp[i][j]表示前i个人第一个队伍的排队时间为j的最小时间,转移比较容易理解

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>

using namespace std;
const int MAXN = 205;

inline int rd(){
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {f=ch=='-'?0:1;ch=getchar();}
    while(isdigit(ch))  {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    return f?x:-x;
}

int n,sum[MAXN],ans=1e9;
int dp[MAXN][MAXN*MAXN];

struct Data{
    int a,b;
}data[MAXN];

inline bool cmp(Data A,Data B){
    return A.b>B.b;
}

int main(){
    memset(dp,0x3f,sizeof(dp));
    n=rd();dp[0][0]=0;
    for(int i=1;i<=n;i++) 
        data[i].a=rd(),data[i].b=rd();
    sort(data+1,data+1+n,cmp);
    for(int i=1;i<=n;i++) sum[i]=sum[i-1]+data[i].a;
    for(int i=1;i<=n;i++)
        for(register int j=0;j<=sum[i];j++){
            if(j>=data[i].a) dp[i][j]=max(dp[i-1][j-data[i].a],j+data[i].b);
            dp[i][j]=min(dp[i][j],max(dp[i-1][j],sum[i]-j+data[i].b));
        }
    for(int i=0;i<=sum[n];i++)
        ans=min(ans,dp[n][i]);
    cout<<ans<<endl;
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/sdfzsyq/p/9683186.html