洛谷题目链接:[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]午餐的更多相关文章

  1. 【题解】洛谷P2577 [ZJOI2005] 午餐(DP+贪心)

    次元传送门:洛谷P2577 思路 首先贪心是必须的 我们能感性地理解出吃饭慢的必须先吃饭(结合一下生活) 因此我们可以先按吃饭时间从大到小排序 然后就能自然地想到用f[i][j][k]表示前i个人在第 ...

  2. 洛谷P2577 [ZJOI2005]午餐 打饭时间作为容量DP

    P2577 [ZJOI2005]午餐 )逼着自己做DP 题意: 有n个人打饭,每个人都有打饭时间和吃饭时间.有两个打饭窗口,问如何安排可以使得总用时最少. 思路: 1)可以发现吃饭时间最长的要先打饭. ...

  3. 洛谷P2577 [ZJOI2005]午餐 dp

    正解:序列dp 解题报告: 传送门! 这题首先要想到一个显然的贪心:每个窗口的排队顺序都是按照吃饭时间从大到小排序的 证明如下: 这种贪心通常都是用微扰法,这题也不例外 现在假如已经确定了每个窗口有哪 ...

  4. 洛谷 P2577 [ZJOI2005]午餐

    这道题目比较难想. 题解: 算法:贪心+dp 容易想到贪心:吃饭慢的先打饭节约时间, 所以先将人按吃饭时间从大到小排序. 然后就是dp了: 首先,应该想到f[i][j][k]:前i个人,在1号窗口打饭 ...

  5. 洛谷 P2577 [ZJOI2005]午餐 题解

    每日一题 day56 打卡 Analysis 算法:贪心+dp 容易想到贪心:吃饭慢的先打饭节约时间, 所以先将人按吃饭时间从大到小排序. 然后就是dp了: 首先,应该想到f[i][j][k]:前i个 ...

  6. BZOJ1899或洛谷2577 [ZJOI2005]午餐

    BZOJ原题链接 洛谷原题链接 解决这题得先想到一个贪心:吃饭慢的先排队. 并不会证明(感觉显然 设\(f[i][j][k]\)表示已经排好了前\(i\)人,第一个队伍需要花费的打饭时间为\(j\), ...

  7. 洛谷 2577 [ZJOI2005]午餐——序列dp

    题目:https://www.luogu.org/problemnew/show/P2577 可以从只有一个窗口的角度思考出一个贪心结论.就是应当按吃饭时间(不算打饭时间)从大到小排序.这样交换相邻两 ...

  8. Luogu P2577 [ZJOI2005]午餐(dp)

    P2577 [ZJOI2005]午餐 题面 题目描述 上午的训练结束了, \(THU \ ACM\) 小组集体去吃午餐,他们一行 \(N\) 人来到了著名的十食堂.这里有两个打饭的窗口,每个窗口同一时 ...

  9. 【洛谷P2577】[ZJOI2005]午餐

    午餐 题目链接 DP题都辣么毒瘤的么.. 首先,看一下题解 我们就有了思路: 贪心:显然,让吃饭慢的先打饭,sort一遍(证明?不存在的.. DP:f[i][j][k]表示前i个人,窗口1的打饭时间为 ...

随机推荐

  1. 11.22Daily Scrum(2)

    人员 任务分配完成情况 明天任务分配 王皓南 实现网页上视频浏览的功能.研究相关的代码和功能.984 数据库测试 申开亮 实现网页上视频浏览的功能.研究相关的代码和功能.985 实现视频浏览的功能 王 ...

  2. UVA725 Division (暴力求解法入门)

    uva 725 Division Write a program that finds and displays all pairs of 5-digit numbers that between t ...

  3. LintCode-373.奇偶分割数组

    奇偶分割数组 分割一个整数数组,使得奇数在前偶数在后. 样例 给定 [1, 2, 3, 4],返回 [1, 3, 2, 4]. 挑战 在原数组中完成,不使用额外空间. 标签 数组 两根指针 code ...

  4. 3dContactPointAnnotationTool开发日志(十三)

      为了使生成的项目能够显示报错信息我又勾选了下面这几个选项:   然后生成的项目运行时可以显示错误信息了,貌似是shader是空的.   之前的代码是这么写的,调用了Shader.Find(),貌似 ...

  5. YaoLingJump开发者日志(六)

      作为一只天才魔法少女狐,不会魔法怎么行?于是我给瑶玲增加了一个技能:魔法弹.   当然,能使用魔法的前提是得有个魔杖,像这样:   魔杖不仅能让瑶玲使用魔法,当瑶玲被攻击时还能提供2s的无敌状态: ...

  6. 软工网络15团队作业——Alpha阶段敏捷冲刺 DAY1

    Alpha阶段敏捷冲刺 DAY1 1.各个成员在 Alpha 阶段认领的任务 姓名 在Alpha阶段所认领的任务 陈龙 题目生成类的编写,随机生成合理题目的算法编写 郑佳明 答案计算类的编写,对随机生 ...

  7. Thinkphp5的ajax接口实现

    前一篇讲到thinkphp5从数据库获取数据之后赋给视图view,前一篇从数据渲染方式来说是服务端数据渲染,这一章则是浏览器端数据渲染.按照知识总结依据来划分,这是两种不同的技术场景. 下面介绍具体的 ...

  8. 身份证验证php

    /**  * 验证身份证号  * @param $vStr  * @return bool  */ function isCreditNo($vStr) {     $vCity = array(   ...

  9. C/S结构 B/S结构

    [1]C/S 结构,即大家熟知的客户机和服务器结构.它是软件系统体系结构,通过它可以充分利用两端硬件环境的优势,将任务合理分配到Client端和Server端来实现,降低了系统的通讯开销.目前大多数应 ...

  10. java 基础 --集合--012

    1, 数组与集合 A:长度不同 数组的长度固定,集合的长度可变 B:内容不同 数组里存储的是同一种类型的元素,而集合可以存储不同类型的元素 C:元素的数据类型问题 数组可以存储基本数据类型,也可以存储 ...