题目描述

上午的训练结束了,THU ACM小组集体去吃午餐,他们一行N人来到了著名的十食堂。这里有两个打饭的窗口,每个窗口同一时刻只能给一个人打饭。由于每个人的口味(以及胃口)不同,所以他们要吃的菜各有不同,打饭所要花费的时间是因人而异的。另外每个人吃饭的速度也不尽相同,所以吃饭花费的时间也是可能有所不同的。

THU ACM小组的吃饭计划是这样的:先把所有的人分成两队,并安排好每队中各人的排列顺序,然后一号队伍到一号窗口去排队打饭,二号队伍到二号窗口去排队打饭。每个人打完饭后立刻开始吃,所有人都吃完饭后立刻集合去六教地下室进行下午的训练。

现在给定了每个人的打饭时间和吃饭时间,要求安排一种最佳的分队和排队方案使得所有人都吃完饭的时间尽量早。

假设THU ACM小组在时刻0到达十食堂,而且食堂里面没有其他吃饭的同学(只有打饭的师傅)。每个人必须而且只能被分在一个队伍里。两个窗口是并行操作互不影响的,而且每个人打饭的时间是和窗口无关的,打完饭之后立刻就开始吃饭,中间没有延迟。

现在给定N个人各自的打饭时间和吃饭时间,要求输出最佳方案下所有人吃完饭的时刻。

输入格式

第一行一个整数N,代表总共有N个人。

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

输出格式

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

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


容易想到的一个贪心策略就是:让打饭慢的人先打饭。所以我们一开始可以对所有人按照打饭时间排序。

然后我们开始考虑窗口的选择。显然,前i个人的最优解一定是由前i-1个人的最优解更新而来的,所以我们可以考虑用动态规划。考虑第i个人怎么选窗口会最优。

第i个人选窗口会影响到的因素就是:在1窗口打饭一共用了多少时间、在2窗口打饭一共用了多少时间。那么我们把这两个量设计进状态即可。设dp[i][j][k]表示前i个人在1窗口用了j个单位时间、在2窗口用了k个单位时间的情况下,前i个人吃完饭的最早时刻。

那么转移很好想,O(1)转移即可。但是进一步分析会发现一个问题:j和k的上限为\(200*200=40000\),这样开数组肯定会爆的...那么想一想优化。

可以发现j和k加起来刚好等于前i个人的打饭时间和。那么换个思路,我们求出前i个人的打饭时间和sum[i],那么我们只需要知道j就可以求出k了。那么我们的状态就可以省掉一维:dp[i][j]表示前i个人在1号窗口用了j个单位时间的情况下,前i个人吃完饭的最早时刻。可以得出转移方程:

\[ dp[i][j]= \left\{ \begin{array}{rcl} min(max(dp[i-1][j-p[i].a],j+p[i].b),max(dp[i-1][j],k+p[i].b)) & j,k>=a[i]\\ max(dp[i-1][j-p[i].a],j+p[i].b) & j>=a[i]\\ max(dp[i-1][j],k+p[i].b) & k>=a[i] \end{array}\right. \]

初始化\(dp[i][j]=inf\),\(dp[0][0]=0\)。答案就是\(Max{\{}dp[n][i]{\}}\)

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#define maxn 201
#define maxm 40001
#define inf 0x3f3f3f3f
using namespace std;inline int read(){register int x(0),f(1); register char c(getchar());while(c<'0'||'9'<c){ if(c=='-') f=-1; c=getchar(); }while('0'<=c&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();return x*f;
}struct node{ int a,b; }p[maxn];
int dp[maxn][maxm];
int n,c[maxn];inline bool cmp(const node &x,const node &y){ return x.b>y.b; }
int main(){n=read();for(register int i=1;i<=n;i++) p[i].a=read(),p[i].b=read();sort(p+1,p+1+n,cmp);for(register int i=1;i<=n;i++) c[i]=c[i-1]+p[i].a;memset(dp,0x3f,sizeof dp),dp[0][0]=0;for(register int i=1;i<=n;i++){for(register int j=0;j<=c[i];j++){register int k=c[i]-j;if(j>=p[i].a && k>=p[i].a) dp[i][j]=min( max( dp[i-1][j-p[i].a],j+p[i].b ),max( dp[i-1][j],k+p[i].b ) );else if(j>=p[i].a) dp[i][j]=max( dp[i-1][j-p[i].a],j+p[i].b );else if(k>=p[i].a) dp[i][j]=max( dp[i-1][j],k+p[i].b );}}int ans=inf;for(register int i=0;i<=c[n];i++) ans=min( ans,dp[n][i] );printf("%d\n",ans);return 0;
}

时间复杂度为\(O(N*40000)\)

转载于:https://www.cnblogs.com/akura/p/11287014.html

[ZJOI2005]午餐相关推荐

  1. ZJOI2005午餐

    描述 上午的训练结束了,THU ACM小组集体去吃午餐,他们一行N人来到了著名的十食堂.这里有两个打饭的窗口,每个窗口同一时刻只能给一个人打饭.由于每个人的口味(以及胃口)不同,所以他们要吃的菜各有不 ...

  2. P2577 [ZJOI2005]午餐

    题面:https://www.luogu.org/problem/P2577 本题一旦设出f[i][j]表示前i个人,在1号窗口打饭总时间j,最早吃完饭的时间 那么就很容易想到 当把i放在1号窗口 f ...

  3. Luogu P2577 [ZJOI2005]午餐

    一道贪心+类背包DP的好题 首先发现一个十分显然的性质,没有这个性质整道题目都难以下手: 无论两队的顺序如何,总是让吃饭慢的人先排队 这是一个很显然的贪心,因为如果让吃饭慢的排在后面要更多的时间至少没 ...

  4. [ZJOI2005]午餐(贪心+dp)

    首先若只有一个窗口,利用贪心,按吃饭时间从大到小排序即可 正确性证明: 定义 eat[i] = 第i个人的吃饭时间,time[i] = 第i个人的打饭时间 延长时间T[i]=max(eat[i]- ∑ ...

  5. [ZJOI2005]午餐 贪心+dp

    这个题如果直接dp的话要考虑 先从题目类型入手,这种规划性问题 应该是个dp 1开始的时间.1结束的时间.2开始的时间.2结束的时间 这是200^6级别的状态数,且没有任何状态优化的余地 所以就要考虑 ...

  6. 2018.12-2019.1 TO-DO LIST

    AC自动机 P3808 [模板]AC自动机(简单版)(完成时间:2018.12.06) P3796 [模板]AC自动机(加强版)(完成时间:2018.12.06) P2444 [POI2000]病毒( ...

  7. 洛谷试炼场 动态规划TG.lv(2)

    P1273 有线电视网 题目描述 某收费有线电视网计划转播一场重要的足球比赛.他们的转播网和用户终端构成一棵树状结构,这棵树的根结点位于足球比赛的现场,树叶为各个用户终端,其他中转站为该树的内部节点. ...

  8. 2018年10月训练记录(10.1~10.23)

    前言 这篇博客记录的是我在201820182018年101010月的刷题列表. 由于时间比较匆忙,可能会有一些空链接,但我会尽快将它们补齐的. (目前链接已补至Oct7thOct\ 7thOct 7t ...

  9. 浪潮刘军:为什么说计算力是AI时代“免费的午餐”?

    出品 | AI科技大本营(ID:rgznai100) 产业AI.元脑生态是浪潮集团2019年度的两大关键词. 作为一家以计算力为核心生产力的企业,浪潮还一直强调人工智能计算是未来最重要的计算力,而无论 ...

最新文章

  1. 计算机在档案管理中的应用,浅谈计算机在档案管理中的应用
  2. 优化XCode的编译速度
  3. android hal 驱动,AndroidHAL-Teseo
  4. c语言加减乘除算术程序,求一个计算加减乘除的C语言程序
  5. 代码 抠图_憋再PS抠图了,3行代码给你安排的明明白白!
  6. php删除两端,php删除字符串末尾子字符,删除开始字符,删除两端字符的示例代码...
  7. 未来:万物皆互联、全民皆社交,人人都是马化腾
  8. Android开发之android与JS互调 | Android与H5互调(附源码)
  9. 超过100G的CVPR 2020 图像匹配挑战赛数据下载!
  10. elasticsearch工具类_Django + Elasticsearch——搜索精彩的TED演讲
  11. 三星官方回应“7nm EUV良率”:内容与事实完全不符
  12. 如何将多个Excel合并到一个Excel中?
  13. 《linux核心应用命令速查》连载十一:pstree:显示进程状态树
  14. yii2.0 读取user表新增字段问题
  15. Ubuntu16.04+ ROS kinetic 使用kinect2 ORK功能包 linemod算法实现可乐罐识别
  16. (收藏)C# .NET开发工具
  17. Esp8266闪存文件系统LIttleFS
  18. 数组最大值/最小值计算方法
  19. 16种css3动画弹出遮罩层
  20. office修复找不到msi_windows7系统下打开office提示缺少pro11msi如何解决

热门文章

  1. interp2 matlab fcn,matlab7.0自动关闭问题(zz)
  2. android制作下拉选择_Excel制作一、二、三级下拉菜单技巧,你一定不能错过
  3. 索引 | 学堂原创推文汇总-v2
  4. 服务器x不会下载mysql_MySQL_解决MySQL数据库死掉以及拒绝服务的方法,从Mysql 5.x的某个版本之后,MySQ - phpStudy...
  5. 若想学 HTML,应从何入手?
  6. Web 前端的路该怎么走?
  7. oracle deul,C#引用传递
  8. style 字体加粗_第9篇 Qt Quick入门教程之基础(九)文本显示和字体
  9. mysql 取模分区_MySQL分区
  10. 怎么把打开方式还原计算机程序,打开方式怎么还原【图文】