[BZOJ1899] [Zjoi2004]Lunch 午餐

题目描述

Description

上午的训练结束了,THU ACM小组集体去吃午餐,他们一行N人来到了著名的十食堂。这里有两个打饭的窗口,每个窗口同一时刻只能给一个人打饭。由于每个人的口味(以及胃口)不同,所以他们要吃的菜各有不同,打饭所要花费的时间是因人而异的。另外每个人吃饭的速度也不尽相同,所以吃饭花费的时间也是可能有所不同的。 THU ACM小组的吃饭计划是这样的:先把所有的人分成两队,并安排好每队中各人的排列顺序,然后一号队伍到一号窗口去排队打饭,二号队伍到二号窗口去排队打饭。每个人打完饭后立刻开始吃,所有人都吃完饭后立刻集合去六教地下室进行下午的训练。 现在给定了每个人的打饭时间和吃饭时间,要求安排一种最佳的分队和排队方案使得所有人都吃完饭的时间尽量早。 假设THU ACM小组在时刻0到达十食堂,而且食堂里面没有其他吃饭的同学(只有打饭的师傅)。每个人必须而且只能被分在一个队伍里。两个窗口是并行操作互不影响的,而且每个人打饭的时间是和窗口无关的,打完饭之后立刻就开始吃饭,中间没有延迟。 现在给定N个人各自的打饭时间和吃饭时间,要求输出最佳方案下所有人吃完饭的时刻。

Input

第一行一个整数N,代表总共有N个人。 以下N行,每行两个整数 Ai,Bi。依次代表第i个人的打饭时间和吃饭时间。

Output

一个整数T,代表所有人吃完饭的最早时刻。

Sample Input

5
2 2
7 7
1 3
6 4
8 5

Sample Output

17

题目分析

动态规划
首先吃饭时间越长 先打越划算 然后按吃饭时间降序排列
表示前i个人,在第一个窗口打饭用时j,所花费最小时间
假设第i个人在一窗口打饭,和这两个状态有关
假设第i个人在二窗口打饭,和这两个状态有关

#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
#include <algorithm>
using namespace std;
int f[210][210*211];
struct your
{
    int a,b;
}q[210];
int sum[210];
int n;
int cmp(your j,your k)
{
    if(j.b==k.b) return j.a<k.a;
    return j.b>k.b;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d%d",&q[i].a,&q[i].b);
    sort(q+1,q+n+1,cmp);
    for(int i=1;i<=n;i++) sum[i]=sum[i-1]+q[i].a;
    memset(f,0x7f,sizeof f);
    f[0][0]=0;
    for(int i=1;i<=n;i++)
        for(int j=0;j<=sum[i];j++)
        {
            if(j>=q[i].a) f[i][j]=min(f[i][j],max(f[i-1][j-q[i].a],j+q[i].b));
            f[i][j]=min(f[i][j],max(f[i-1][j],sum[i]-j+q[i].b));
        }
    int ans=0x7f7f7f7f;
    for(int i=0;i<=sum[n];i++) ans=min(ans,f[n][i]);
    printf("%d",ans);
    return 0;
}

发表评论

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