[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的正整数。

Solution

首先一个显而易见的贪心:一个人吃饭的时间越久,为了达成我们的目标,我们要尽量让他先吃

所以按吃饭时间从大到小排序

首先,我们知道肯定是需要枚举当前是第几个人打饭的,但是仅仅这样不足以确定我们的状态,所以我们还要确定当前情况下1号窗口和2号窗口分别已经排了多长时间的队。因此,dp[i][j][k]表示当前处理到第i个人1号窗口排队时间为j,2号窗口排队时间为k的最小吃饭时间

if(j>=t[i].a) dp[i][j][k]=min(dp[i][j][k],max(dp[i-1][j-t[i].a][k],j+t[i].b));
//dp[i-1][j-t[i].a][k]表示第i个人排队和吃饭的时间还不足前i-1个人吃饭的时间,所以没有造成影响
//后面的j+t[i].b就是造成了影响
if(k>=t[i].a) dp[i][j][k]=min(dp[i][j][k],max(dp[i-1][j][k-t[i].a],k+t[i].b));
//同上

我们发现这个数组会爆内存,怎么优化呢?

无论是选1号窗口还是2号窗口,前i个人的排队时间总和是不变的,我们就可以通过j求出k,前缀和就好了

那么方程就变成了这样

if(j>=t[i].a) dp[i][j]=min(dp[i][j],max(dp[i-1][j-t[i].a],j+t[i].b));
dp[i][j]=min(dp[i][j],max(dp[i-1][j],sum[i]-j+t[i].b));//sum[i]-j就是k

dp边界:dp[0][0]=0,其他的都赋为inf就好了,毕竟是要求最小值嘛

Code

#include<bits/stdc++.h>
using namespace std;
const int N=210;
struct node {
int a,b;
bool operator < (const node &c) const{return b>c.b;}
}t[N];
int n,ans;
int sum[N],dp[N][N*N];
int main()
{
ios::sync_with_stdio(0);
cin>>n;
for(int i=1;i<=n;i++)
cin>>t[i].a>>t[i].b;
sort(t+1,t+1+n);
for(int i=1;i<=n;i++)
sum[i]=sum[i-1]+t[i].a;
memset(dp,0x3f,sizeof(dp)); ans=dp[0][0],dp[0][0]=0;
for(int i=1;i<=n;i++) {
for(int j=0;j<=sum[i];j++) {
if(j>=t[i].a) dp[i][j]=min(dp[i][j],max(dp[i-1][j-t[i].a],j+t[i].b));
dp[i][j]=min(dp[i][j],max(dp[i-1][j],sum[i]-j+t[i].b));
}
}
for(int i=1;i<=sum[n];i++)
ans=min(ans,dp[n][i]);
cout<<ans<<endl;
}

博主蒟蒻,随意转载.但必须附上原文链接

http://www.cnblogs.com/real-l/

[ZJOI2005]午餐 (DP)的更多相关文章

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

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

  2. P2577 [ZJOI2005]午餐[DP]

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

  3. 洛谷P2577 [ZJOI2005]午餐 dp

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

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

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

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

    洛谷题目链接:[ZJOI2005]午餐 题目描述 上午的训练结束了,THU ACM小组集体去吃午餐,他们一行N人来到了著名的十食堂.这里有两个打饭的窗口,每个窗口同一时刻只能给一个人打饭.由于每个人的 ...

  6. P2577 [ZJOI2005]午餐 状压DP

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

  7. Luogu2577 | [ZJOI2005]午餐 (贪心+DP)

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

  8. 【洛谷2577】[ZJOI2005] 午餐(较水DP)

    点此看题面 大致题意: 有\(N\)个学生去食堂打饭,每个学生有两个属性:打饭时间\(a_i\)和吃饭时间\(b_i\).现要求将这些学生分成两队分别打饭,求最早何时所有人吃完饭. 贪心 首先,依据贪 ...

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

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

随机推荐

  1. django的模型和基本的脚本命令

    python manage.py startproject project_name  创建一个django项目 python manage.py startapp app_name  创建一个app ...

  2. 003---Python基本数据类型--列表

    列表 .caret, .dropup > .btn > .caret { border-top-color: #000 !important; } .label { border: 1px ...

  3. VS中的快捷键

    1.代码中追踪函数的详细代码:   F12

  4. LeetCode:22. Generate Parentheses(Medium)

    1. 原题链接 https://leetcode.com/problems/generate-parentheses/description/ 2. 题目要求 给出一个正整数n,请求出由n对合法的圆括 ...

  5. JAXB轻松转换xml对象和java对象

    实体类如下: package com.cn.entity; import java.util.List; import javax.xml.bind.annotation.XmlAccessType; ...

  6. How to find your web part

         When we deploy a web part, we can find it on any pages through the follow steps:      Firstly, ...

  7. 「日常训练」Single-use Stones (CFR476D2D)

    题意(Codeforces 965D) $w$表示河的宽度,$l$表示青蛙所能跳的最远的距离,第二行的$w-1$个元素表示离河岸为$i$的地方有$a[i]$个石头,一个石头被踩两次,问最多有多少只青蛙 ...

  8. CS229 1

    1.机器学习 机器学习是工具,具体应用到某个实际场景下,才是目的. 2.分类 a 监督学习,包括回归(regression),分类(classification).回归问题,数据可以是连续或者离散,分 ...

  9. javascript中容易出bug的语句

    一.forEach方法 forEach方法中没法用continue来实现跳过单句到下一次循环,如果要跳到下一次循环,要用return关键字,如果想直接跳出forEach循环,具我所知的,要throw一 ...

  10. 6.爬虫 requests库讲解 总结

    requests库的总结: 用ProcessOn根据前面的几节内容做了个思维导图: