【bzoj1899】[Zjoi2004]Lunch 午餐(贪心+dp)

  题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=1899

  显然为了节省时间,吃饭慢的人要先打饭。于是我们可以先把所有人按吃饭时间排序,于是问题就变成了把人们按顺序分配到两条队列中。这样就可以dp了。

  设$ f[i][j] $表示前$ i $个人打饭+吃饭,第一个窗口排队$ j $分钟所用的最少时间,于是:

  $ f[i][j]=\min(\max(f[i-1][j],Sum_i-j+B_i),\max(f[i-1][j-A_i],j+B_i)) $(这里$ Sum_i $表示前$ i $个人打饭用的总时间)

  代码:

#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<iostream> 
#include<algorithm>
#include<queue>
#include<vector>
#include<map>
#define ll long long
#define ull unsigned long long
#define max(a,b) (a>b?a:b)
#define min(a,b) (a<b?a:b)
#define lowbit(x) (x& -x)
#define mod 1000000007
#define inf 0x3f3f3f3f
#define eps 1e-18
#define maxn 100010
inline ll read(){ll tmp=0; char c=getchar(),f=1; for(;c<'0'||'9'<c;c=getchar())if(c=='-')f=-1; for(;'0'<=c&&c<='9';c=getchar())tmp=(tmp<<3)+(tmp<<1)+c-'0'; return tmp*f;}
inline ll power(ll a,ll b){ll ans=1; for(;b;b>>=1){if(b&1)ans=ans*a%mod; a=a*a%mod;} return ans;}
inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
inline void swap(int &a,int &b){int tmp=a; a=b; b=tmp;}
using namespace std;
struct data{
    int x,y;
}a[210];
int f[210][40010];
int sum[210];
int n;
bool cmp(data a,data b){return a.y>b.y;}
int main()
{
    n=read();
    for(int i=1;i<=n;i++)
        a[i].x=read(),a[i].y=read();
    sort(a+1,a+n+1,cmp);
    for(int i=1;i<=n;i++)sum[i]=sum[i-1]+a[i].x;
    memset(f,0x3f,sizeof(f)); f[0][0]=0;
    for(int i=1;i<=n;i++)
        for(int j=0;j<=sum[i];j++){
            f[i][j]=max(f[i-1][j],sum[i]-j+a[i].y);
            if(j>=a[i].x)f[i][j]=min(f[i][j],max(f[i-1][j-a[i].x],j+a[i].y));
        }
    int ans=inf;
    for(int i=0;i<=sum[n];i++)
        ans=min(ans,f[n][i]);
    printf("%d\n",ans);
}
bzoj1899

 

posted @ 2018-09-06 13:53  QuartZ_Z  阅读(144)  评论(0编辑  收藏  举报