[洛谷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的打饭时间为 ...
随机推荐
- python函数中的位置参数、默认参数、关键字参数、可变参数区别
一.位置参数 调用函数时根据函数定义的参数位置来传递参数. #!/usr/bin/env python # coding=utf-8 def print_hello(name, sex): sex_d ...
- 《剑指Offer》题二十一~题三十
二十一.调整数组顺序使奇数位于偶数前面 题目:输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分. 测试用例: 功能测试:输入数组中的奇 ...
- 详解实现Android中实现View滑动的几种方式
注: 本文提到的所有三种滑动方式的完整demo:ScrollDemo 1. 关于View我们需要知道的 (1)什么是View? Android中的View类是所有UI控件的基类(Base class) ...
- ZigBee设备入网流程之关联方式
ZigBee设备入网流程 ZigBee设备入网有关联方式和直接方式两种,我所熟悉的是关联方式,这也是最常用的方式. 关联方式 step1 设备发出Beacon Request 设备会在预先设置的几个信 ...
- alpha阶段个人总结(201521123031林庭亦)
一.个人总结 第一部分:硬的问题 第二部分:软的问题,在成长路上学到了什么? 1 当你看到不靠谱的设计.糟糕的代码.过时的文档和测试用例的时候,不要想 "既然别人的代码已经这样了,我的代码也 ...
- InstallShield Limited Edition for Visual Studio 国内注册时国家无下拉框解决方法
注册地址:http://learn.flexerasoftware.com/content/IS-EVAL-InstallShield-Limited-Edition-Visual-Studio 火狐 ...
- POJ 2785 4 Values whose Sum is 0(折半枚举)
给出四个长度为n的数列a,b,c,d,求从这四个数列中每个选取一个元素后的和为0的方法数.n<=4000,abs(val)<=2^28. 考虑直接暴力,复杂度O(n^4).显然超时. # ...
- 【bzoj1705】[Usaco2007 Nov]Telephone Wire 架设电话线 dp
题目描述 最近,Farmer John的奶牛们越来越不满于牛棚里一塌糊涂的电话服务 于是,她们要求FJ把那些老旧的电话线换成性能更好的新电话线. 新的电话线架设在已有的N(2 <= N < ...
- 前端基础:HTML标签(下)
前端基础HTML标签(下) 1.表单 表单的功能主要用于向服务器传输数据,从而实现客户端与Web服务器的交互.表单能够包含input系列标签,比如:文本字段.复选框.单选按钮.提交按钮等:表单还包含t ...
- BZOJ 3040最短路
题目描述 给定一个 NN 个点, MM 条有向边的带权图,请你计算从 SS 出发,到每个点的距离. 数据保证你能从 SS 出发到任意点. 输入输出格式 输入格式: 第一行两个整数 NN . MM ,表 ...