[洛谷P2577] [ZJOI2005]午餐
洛谷题目链接:[ZJOI2005]午餐
题目描述
上午的训练结束了,THU ACM小组集体去吃午餐,他们一行N人来到了著名的十食堂。这里有两个打饭的窗口,每个窗口同一时刻只能给一个人打饭。由于每个人的口味(以及胃口)不同,所以他们要吃的菜各有不同,打饭所要花费的时间是因人而异的。另外每个人吃饭的速度也不尽相同,所以吃饭花费的时间也是可能有所不同的。
THU ACM小组的吃饭计划是这样的:先把所有的人分成两队,并安排好每队中各人的排列顺序,然后一号队伍到一号窗口去排队打饭,二号队伍到二号窗口去排队打饭。每个人打完饭后立刻开始吃,所有人都吃完饭后立刻集合去六教地下室进行下午的训练。
现在给定了每个人的打饭时间和吃饭时间,要求安排一种最佳的分队和排队方案使得所有人都吃完饭的时间尽量早。
假设THU ACM小组在时刻0到达十食堂,而且食堂里面没有其他吃饭的同学(只有打饭的师傅)。每个人必须而且只能被分在一个队伍里。两个窗口是并行操作互不影响的,而且每个人打饭的时间是和窗口无关的,打完饭之后立刻就开始吃饭,中间没有延迟。
现在给定N个人各自的打饭时间和吃饭时间,要求输出最佳方案下所有人吃完饭的时刻。
输入输出格式
输入格式:
第一行一个整数N,代表总共有N个人。
以下N行,每行两个整数 Ai,Bi。依次代表第i个人的打饭时间和吃饭时间。
输出格式:
一个整数T,代表所有人吃完饭的最早时刻。
输入输出样例
输入样例#1:
5
2 2
7 7
1 3
6 4
8 5
输出样例#1:
17
说明
所有输入数据均为不超过200的正整数。
题意: 有\(n\)个人.,每个人有一个排队时间和吃饭时间,两个窗口,窗口每时每刻都可以有一个人在排队,且一个人排完队后另一个人可以马上接着他排队,要使每个人都打完饭吃完最短需要多久.
题解: 首先我们先想一下如果只有一个窗口该如何记录最短时间.如果只有一个窗口,那么最短时间就只与排队顺序有关了,那么应该让谁排在前面呢?我们这里假设\(i\)的等待时间为\(wait[i]\),吃饭时间为\(eat[i]\),假设要让\(i\)排在\(j\)前面,就要满足:\(wait[i]+wait[j]+eat[j] <= wait[j]+wait[i]+eat[i])\)
化一下式子,可以得到\(eat[i] >= eat[j]\),也就是说,按照吃东西的时间从大到小排序,这样可以得到的结果是最优的.
那么如果有两个窗口呢?这里我们可以用DP的方法来维护一下.我们用状态\(f[i][j][k]\)表示前\(i\)个人都吃完饭,且在第一个窗口等待时间为\(j\),第二个为\(k\)所需要的最少时间.那么可以写出状态转移方程:$$f[i][j][k]=min(f[i][j][k], max(f[i-1][j-wait[i]][k], j+eat[i]))$$和$$f[i][j][k]=min(f[i][j][k], max(f[i-1][j][k-wait[i]], k+eat[i]))$$.
然而这样做的话时空复杂度是\(O(n*V^2)\)的,其中\(V=n^2\),显然这样的复杂度是过不了的.
那么我们需要对这个状态进行一些优化.
我们会发现前\(i\)个人的等待时间之和是可以确定的,也就是说,我们并不需要记录两个窗口的等待时间,只需要记录一个窗口的等待时间就可以算出另一个窗口的等待时间,可以设状态\(f[i][j]\)表示前\(i\)个人都吃完饭,并且第一个窗口等待时间为\(j\).这样定义的状态可以保证是唯一的.转移也类似上面的转移方法:$$f[i][j] =min(f[i][j], max(f[i-1][j-wait[i]], j+eat[i]))$$和$$f[i][j] = min(f[i][j], max(f[i-1][j], sum[i]-j+eat[i]))$$其中\(sum[i]\)表示前\(i\)个人的等待总时间.
#include<bits/stdc++.h>
using namespace std;
const int N = 200+5;
typedef int _int;
#define int long long
int n, sum[N], ans = 2e9;
int f[N][N*N];
struct people{
int wait, eat;
}a[N];
bool cmpp(people a, people b){ return a.eat > b.eat; }
_int main(){
ios::sync_with_stdio(false);
cin >> n;
for(int i = 1; i <= n; i++) cin >> a[i].wait >> a[i].eat;
sort(a+1, a+n+1, cmpp);
for(int i = 1; i <= n; i++) sum[i] = sum[i-1]+a[i].wait;
memset(f, 127/3, sizeof(f)), f[0][0] = 0;
for(int i = 1; i <= n; i++)
for(int j = 0; j <= sum[n]; j++){
if(j >= a[i].wait) f[i][j] = min(f[i][j], max(f[i-1][j-a[i].wait], j+a[i].eat));
f[i][j] = min(f[i][j], max(f[i-1][j], sum[i]-j+a[i].eat));
}
for(int i = 0; i <= sum[n]; i++) ans = min(ans, f[n][i]);
cout << ans << endl;
return 0;
}
[洛谷P2577] [ZJOI2005]午餐的更多相关文章
- 【题解】洛谷P2577 [ZJOI2005] 午餐(DP+贪心)
次元传送门:洛谷P2577 思路 首先贪心是必须的 我们能感性地理解出吃饭慢的必须先吃饭(结合一下生活) 因此我们可以先按吃饭时间从大到小排序 然后就能自然地想到用f[i][j][k]表示前i个人在第 ...
- 洛谷P2577 [ZJOI2005]午餐 打饭时间作为容量DP
P2577 [ZJOI2005]午餐 )逼着自己做DP 题意: 有n个人打饭,每个人都有打饭时间和吃饭时间.有两个打饭窗口,问如何安排可以使得总用时最少. 思路: 1)可以发现吃饭时间最长的要先打饭. ...
- 洛谷P2577 [ZJOI2005]午餐 dp
正解:序列dp 解题报告: 传送门! 这题首先要想到一个显然的贪心:每个窗口的排队顺序都是按照吃饭时间从大到小排序的 证明如下: 这种贪心通常都是用微扰法,这题也不例外 现在假如已经确定了每个窗口有哪 ...
- 洛谷 P2577 [ZJOI2005]午餐
这道题目比较难想. 题解: 算法:贪心+dp 容易想到贪心:吃饭慢的先打饭节约时间, 所以先将人按吃饭时间从大到小排序. 然后就是dp了: 首先,应该想到f[i][j][k]:前i个人,在1号窗口打饭 ...
- 洛谷 P2577 [ZJOI2005]午餐 题解
每日一题 day56 打卡 Analysis 算法:贪心+dp 容易想到贪心:吃饭慢的先打饭节约时间, 所以先将人按吃饭时间从大到小排序. 然后就是dp了: 首先,应该想到f[i][j][k]:前i个 ...
- BZOJ1899或洛谷2577 [ZJOI2005]午餐
BZOJ原题链接 洛谷原题链接 解决这题得先想到一个贪心:吃饭慢的先排队. 并不会证明(感觉显然 设\(f[i][j][k]\)表示已经排好了前\(i\)人,第一个队伍需要花费的打饭时间为\(j\), ...
- 洛谷 2577 [ZJOI2005]午餐——序列dp
题目:https://www.luogu.org/problemnew/show/P2577 可以从只有一个窗口的角度思考出一个贪心结论.就是应当按吃饭时间(不算打饭时间)从大到小排序.这样交换相邻两 ...
- Luogu P2577 [ZJOI2005]午餐(dp)
P2577 [ZJOI2005]午餐 题面 题目描述 上午的训练结束了, \(THU \ ACM\) 小组集体去吃午餐,他们一行 \(N\) 人来到了著名的十食堂.这里有两个打饭的窗口,每个窗口同一时 ...
- 【洛谷P2577】[ZJOI2005]午餐
午餐 题目链接 DP题都辣么毒瘤的么.. 首先,看一下题解 我们就有了思路: 贪心:显然,让吃饭慢的先打饭,sort一遍(证明?不存在的.. DP:f[i][j][k]表示前i个人,窗口1的打饭时间为 ...
随机推荐
- PHP 5.6.32 增加pdo_dblib.so拓展
首先说明,php增加pdo_dblib.so拓展不需要重新编译php源文件,只需要增加dblib源包即可. 1.下载安装所需包 1.#下载 wget http://mirrors.ibiblio.or ...
- Python 元组 集合
1. 元组 >>> a = (1,2,3,4,5) >>> b = list(a) #转换成列表对象, 可以更改 >>> b [1, 2, 3, ...
- linux上使用J-Link调试S3C2440裸机代码
linux上使用J-Link调试S3C2440裸机代码 工具: segger的jlink仿真器 segger的jlink for linux 交叉编译工具链里面的arm-xx-linux-xx-gdb ...
- 3dContactPointAnnotationTool开发日志(三)
今天的目的是把obj文件导到场景里.具体将制定路径的obj文件导进去我用的是这个方法.导进去后呈现的是一个黑色的影子. 导入后还想实现一下缩放功能,请看这个方法.缩放实现起来也很简单. 光 ...
- 2018 杭电多校1 - Distinct Values
题目链接 Problem Description Chiaki has an array of n positive integers. You are told some facts about t ...
- BZOJ 1816 扑克牌(二分)
由于答案具有单调性,考虑二分答案并验证. 如果能凑齐x堆,因为每个joke在一个牌堆里最多只能用一次,则至多只能用min(x,m)个joke. 对于每个牌,如果这个牌的总数小于x,用joke补齐剩下的 ...
- CSS-posiziton
1. 想要实现,”返回顶部”永远位于页面的右下角.需要用到position函数.CSS:层叠样式表.用到了分层的功能. position:fixed; 永远固定在一个地方. <!DOCTYPE ...
- [bzoj] 2657 ZJOI2012 旅游 || bfs
原题 题意: 一个多边形,三角剖分,求一条对角线最多能经过多少三角形 题解: 因为不涉及坐标之类的,所以根几何肯定一点关系都没有. 我们会发现,对于有共边的两个三角形,可以被同一条线穿过,而这就相当于 ...
- [bzoj] 1068 压缩 || 区间dp
原题 f[i][j][0/1]表示i-1处有一个M,i到j压缩后的长度,0/1表示i到j中有没有m. 初始为j-i+1 f[i][j][0]=min(f[i][j][0],f[i][k][0]+j-k ...
- cf 442 div2 F. Ann and Books(莫队算法)
cf 442 div2 F. Ann and Books(莫队算法) 题意: \(给出n和k,和a_i,sum_i表示前i个数的和,有q个查询[l,r]\) 每次查询区间\([l,r]内有多少对(i, ...