【P2577】 午餐
题目简述
THU ACM小组一行N个人去食堂吃饭,计划是这样的:先把所有的人分成两队,并安排好每队中各人的排列顺序,然后一号队伍到一号窗口去排队打饭,二号队伍到二号窗口去排队打饭。每个人打完饭后立刻开始吃,所有人都吃完饭后立刻集合去六教地下室进行下午的训练。
现在给定了每个人的打饭时间和吃饭时间,要求安排一种最佳的分队和排队方案使得所有人都吃完饭的时间尽量早。
假设THU ACM小组在时刻0到达十食堂,而且食堂里面没有其他吃饭的同学(只有打饭的师傅)。每个人必须而且只能被分在一个队伍里。两个窗口是并行操作互不影响的,而且每个人打饭的时间是和窗口无关的,打完饭之后立刻就开始吃饭,中间没有延迟。
现在给定N个人各自的打饭时间和吃饭时间,要求输出最佳方案下所有人吃完饭的时刻。
输入输出格式
输入格式:
第一行一个整数N,代表总共有N个人。
以下N行,每行两个整数 Ai,Bi。依次代表第i个人的打饭时间和吃饭时间。
输出格式:
一个整数T,代表所有人吃完饭的最早时刻。
说明
所有输入数据均为不超过200的正整数。
solution
一道比较难想的动态规划(只是对于本蒟蒻),这道题的大体思路是贪心+DP
贪心是将N个人按照Bi的顺序排序,吃饭时间长的人放到前面盛饭
首先简化问题,假定只有一个打饭窗口,且定义延后时间T,第i个人的延后时间记作T[i],则T[i]=max(eat[i] - Σ(i<j<=N)time[j] , 0)其中j∈Z,N为总人数,time[j]表示第j个人的打饭时间,eat[j],表示第j个人的吃饭时间。显然,最后的集合时间为Σ(1<=j<=N)time[j] + max{T[j] , j∈[1,N]}。
将人按照eat大小从大到小排序后,可以证明此时max{T[j] , j∈[1,N]}最小,因为任何顺序改变都会导致max{T[j] , j∈[1,N]}增加(或至少持平),而Σ(1<=j<=N)time[j]不会改变。所以将人按照eat大小从大到小排序后,最后集合时间最短。我们可以很容易地将此结论推广到两支队伍的情况,从而证明贪心的正确性。
然后进行DP
DP[i][j]表示i个人盛饭排队共耗时j时最少话费的总时间
得出状态转移方程
for(re int i=;i<=n;++i)//i表示当前第i个人
{
for(re int j=;j<=sum[i];++j)//j表示当前花费的等待时间
{
if(j>=stu[i].a)
DP[i][j]=min(DP[i][j],max(DP[i-][j-stu[i].a],j+stu[i].b));//第一个队列花费的时间由max(DP[i-1][j-stu[i].a],j+stu[i].b)转移而来
//DP[i-1][j-stu[i].a]表示除去第i个人的总时间,因为有可能前面i-1个人还没吃饭第i个人就吃完了(队伍最后离开的是前i-1个人)
//j+stu[i]表示第i个人排队吃饭的时间(队伍最后离开的是第i个人)
DP[i][j]=min(DP[i][j],max(DP[i-][j],sum[i]-j+stu[i].b));//i在第二个队列的情况
//同上,DP[i-1][j]表示第i个人影响不到前面人的等待总时间
//sum[i]是前i个人的等待时间总和
}
}
code
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cstring>
#define maxn 205
#define maxt 40010
#define re register
using namespace std;
int DP[maxn][maxt],sum[maxn],n;
struct POP{
int a,b;
}stu[maxn];
inline int read()
{
int x=,f=; char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
bool cmp(POP A,POP B)
{
return A.b>B.b;
}
int main()
{
n=read();
for(re int i=;i<=n;++i)
{
stu[i].a=read();
stu[i].b=read(); }
memset(DP,,sizeof(DP));
sort(stu+,stu+n+,cmp);
for(re int i=;i<=n;++i)
{
sum[i]=sum[i-]+stu[i].a;
}jiufftts
DP[][]=;
for(re int i=;i<=n;++i)
{
for(re int j=;j<=sum[i];++j)
{
if(j>=stu[i].a)
DP[i][j]=min(DP[i][j],max(DP[i-][j-stu[i].a],j+stu[i].b)); DP[i][j]=min(DP[i][j],max(DP[i-][j],sum[i]-j+stu[i].b));
}
}
int ans=;
for(re int i=;i<=sum[n];++i)
ans=min(ans,DP[n][i]);
printf("%d",ans);
return ;
}
【P2577】 午餐的更多相关文章
- 洛谷P2577 午餐【贪心】【线性dp】
题目:https://www.luogu.org/problemnew/show/P2577 题意:n个人每个人有一个打饭时间和吃饭时间,将他们分成两个队伍.每个人打到饭之后就马上去吃饭.问怎么安排可 ...
- 洛谷 [P2577] 午餐
DP + 贪心 我们发现,如果只有一个窗口,贪心即可解决,吃饭时间长的人一定要先打饭 有两个窗口的时候,这条性质依然满足,但是两个窗口如何分配,需要 01 背包 #include <iostre ...
- 洛谷P2577 午餐
题目链接 题意概述:有n个人,第i个人打饭消耗ai时间,离开后吃饭耗费bi时间,将n个人分成两队,合理分配人员使总时间最短并输出总时间. 我们把问题拆分为两个部分.首先是排列顺序,然后是怎么分到两个队 ...
- 洛谷P2577 [ZJOI2005]午餐 打饭时间作为容量DP
P2577 [ZJOI2005]午餐 )逼着自己做DP 题意: 有n个人打饭,每个人都有打饭时间和吃饭时间.有两个打饭窗口,问如何安排可以使得总用时最少. 思路: 1)可以发现吃饭时间最长的要先打饭. ...
- Luogu P2577 [ZJOI2005]午餐(dp)
P2577 [ZJOI2005]午餐 题面 题目描述 上午的训练结束了, \(THU \ ACM\) 小组集体去吃午餐,他们一行 \(N\) 人来到了著名的十食堂.这里有两个打饭的窗口,每个窗口同一时 ...
- P2577 [ZJOI2005]午餐 状压DP
题目描述 上午的训练结束了,THU ACM小组集体去吃午餐,他们一行N人来到了著名的十食堂.这里有两个打饭的窗口,每个窗口同一时刻只能给一个人打饭.由于每个人的口味(以及胃口)不同,所以他们要吃的菜各 ...
- P2577 [ZJOI2005]午餐
题目描述 上午的训练结束了,THU ACM小组集体去吃午餐,他们一行N人来到了著名的十食堂.这里有两个打饭的窗口,每个窗口同一时刻只能给一个人打饭.由于每个人的口味(以及胃口)不同,所以他们要吃的菜各 ...
- 【题解】洛谷P2577 [ZJOI2005] 午餐(DP+贪心)
次元传送门:洛谷P2577 思路 首先贪心是必须的 我们能感性地理解出吃饭慢的必须先吃饭(结合一下生活) 因此我们可以先按吃饭时间从大到小排序 然后就能自然地想到用f[i][j][k]表示前i个人在第 ...
- [洛谷P2577] [ZJOI2005]午餐
洛谷题目链接:[ZJOI2005]午餐 题目描述 上午的训练结束了,THU ACM小组集体去吃午餐,他们一行N人来到了著名的十食堂.这里有两个打饭的窗口,每个窗口同一时刻只能给一个人打饭.由于每个人的 ...
- 【洛谷P2577】[ZJOI2005]午餐
午餐 题目链接 DP题都辣么毒瘤的么.. 首先,看一下题解 我们就有了思路: 贪心:显然,让吃饭慢的先打饭,sort一遍(证明?不存在的.. DP:f[i][j][k]表示前i个人,窗口1的打饭时间为 ...
随机推荐
- @SuppressWarnings("rawtypes") 是什么含义
简介:java.lang.SuppressWarnings是J2SE 5.0中标准的Annotation之一.可以标注在类.字段.方法.参数.构造方法,以及局部变量上.作用:告诉编译器忽略指定的警告, ...
- Pandas学习笔记
本学习笔记来自于莫烦Python,原视频链接 一.Pandas基本介绍和使用 Series数据结构:索引在左,值在右 import pandas as pd import numpy as np s ...
- Linux中Mysql的简介和安装
MySQL 简介 点击查看MySQL官方网站 MySQL是一个关系型数据库管理系统,由瑞典MySQL AB公司开发,后来被Sun公司收购,Sun公司后来又被Oracle公司收购,目前属于Oracle旗 ...
- 总结C语言字符检测函数:isalnum、isalpha...
前言:最近一直在刷leetcode的题,用到isalnum函数,用man手册查找了一下,总共有13个相关函数如下: #include <ctype.h> int isalnum(int c ...
- [开源]基于Log4Net简单实现KafkaAppender
背景 基于之前基于Log4Net本地日志服务简单实现 实现本地日志服务,但是随着项目开发演进,本地日志服务满足不了需求,譬如在预发布环境或者生产环境,不可能让开发人员登录查看本地日志文件分析. Kaf ...
- 遇到一道经典的java面试题
在文件 nameList.txt 中按下图格式存放着超过50万人的姓名与身份证信息.请使用您熟悉的编程语言(Java或C/C++)编写一段程序, 将出生日期落在1995年1月1日与1999年12月31 ...
- 数据结构系列(2)之 AVL 树
本文将主要讲解平衡二叉树中的 AVL 树,其中将重点讲解二叉树的重平衡方法,即左旋和右旋,以及 3+4 重构:这些方法都是后面要讲的 B 树,红黑树等 BBST 的重要基础:此外在看本文之前最好先看一 ...
- [Javascript] encodeURIComponent()方法
在vue項目中使用vue-router通过url进行传值 encodeURIComponent encodeURIComponent() 函数可把字符串作为 URI 组件进行编码.encodeURIC ...
- C# 委托基础1.0
在C# 1.0中提出了一种新特性叫作:委托.委托本质上一种类型.是对特定方法的抽象,定义委托后,可以将方法封装,把方法当参数,传递 using System; using System.Collect ...
- DSAPI TreeView节点增删简化操作
将一行或多行字符串添加到TreeView控件. 函数: 控件.TreeView控件.添加路径节点到TreeView(要添加节点的TreeView控件,字符串或字符串数组) 示例:将一个多行文本添加到T ...