zoukankan      html  css  js  c++  java
  • 【BZOJ1899】[Zjoi2004]Lunch 午餐 贪心+DP

    【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

    HINT

    方案如下:

    窗口1: 窗口2:
    7 7 1 3
    6 4 8 5
    2 2

    【限制】
    所有输入数据均为不超过200的正整数。

    题解:首先自己讨论一下就能知道,如果只有一个队列,那么一定是让吃饭时间慢的先打饭。那么如果有两个队列,那么其中的每一个都一定是按吃饭时间递减的,所以我们先将所有人按吃饭时间排序。

    然后设f[i][j][k]表示前i个人,A队列总等待时间为j,B队列总等待时间为k,所需要的最小总时间。下一步比较神,用sum[i]表示前i个人等待时间的前缀和,则j+k=sum[i],所以我们可以优化掉一维。

    然后就容易DP了。

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    struct node
    {
    	int a,b;
    }p[210];
    int n,m,sum,ans;
    int f[2][40010];
    inline int rd()
    {
    	int ret=0,f=1;	char gc=getchar();
    	while(gc<'0'||gc>'9')	{if(gc=='-')f=-f;	gc=getchar();}
    	while(gc>='0'&&gc<='9')	ret=ret*10+gc-'0',gc=getchar();
    	return ret*f;
    }
    bool cmp(node a,node b)
    {
    	return a.b>b.b;
    }
    int main()
    {
    	n=rd();
    	int i,j,d;
    	for(i=1;i<=n;i++)	p[i].a=rd(),p[i].b=rd();
    	sort(p+1,p+n+1,cmp);
    	memset(f,0x3f,sizeof(f));
    	f[0][0]=0;
    	for(i=1;i<=n;i++)
    	{
    		d=i&1,memset(f[d],0x3f,sizeof(int)*(sum+1)),sum+=p[i].a;
    		for(j=0;j<=sum;j++)
    		{
    			f[d][j]=max(f[d^1][j],sum-j+p[i].b);
    			if(j>=p[i].a)	f[d][j]=min(f[d][j],max(f[d^1][j-p[i].a],j+p[i].b));
    		}
    	}
    	ans=1<<30;
    	for(i=0;i<=sum;i++)	ans=min(ans,f[n&1][i]);
    	printf("%d",ans);
    	return 0;
    }
  • 相关阅读:
    ClickOne :添加ClickOnce程序的快捷方式
    C#: 通过html调用WinForm 。。。。。
    JQuery:常用方法一览
    Jquery:Ajax解析XML数据(同步及异步调用)
    系统管理:服务器超级隐藏账户的建立与检测大全[转载]
    Jquery :动态给Table指定行或尾行插入tr和相关,遍历页面所有控件获取id
    .Net : webBrowser弹出新页面,在当前Form窗体打开,可设置屏蔽当前网页的js错误。。。。
    Visual Studio 设置:包括根据不同类型的开发活动对集成开发环境 (IDE) 所做的各种自定义设置
    VB.Net : ApplicationEvents类中,创建主程序的快捷方式 , 捕获程序未Try的错误及抛出相关的类和方法名 , 是否联机等相关。。
    [转载]JavaScript 图片预览效果
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/7468822.html
Copyright © 2011-2022 走看看