描述
上午的训练结束了,THU ACM小组集体去吃午餐,他们一行N人来到了著名的十食堂。这里有两个打饭的窗口,每个窗口同一时刻只能给一个人打饭。由于每个人的口味(以及胃口)不同,所以他们要吃的菜各有不同,打饭所要花费的时间是因人而异的。另外每个人吃饭的速度也不尽相同,所以吃饭花费的时间也是可能有所不同的。
THU ACM小组的吃饭计划是这样的:先把所有的人分成两队,并安排好每队中各人的排列顺序,然后一号队伍到一号窗口去排队打饭,二号队伍到二号窗口去排队打饭。每个人打完饭后立刻开始吃,所有人都吃完饭后立刻集合去六教地下室进行下午的训练。
现在给定了每个人的打饭时间和吃饭时间,要求安排一种最佳的分队和排队方案使得所有人都吃完饭的时间尽量早。
假设THU ACM小组在时刻0到达十食堂,而且食堂里面没有其他吃饭的同学(只有打饭的师傅)。每个人必须而且只能被分在一个队伍里。两个窗口是并行操作互不影响的,而且每个人打饭的时间是和窗口无关的,打完饭之后立刻就开始吃饭,中间没有延迟。
现在给定N个人各自的打饭时间和吃饭时间,要求输出最佳方案下所有人吃完饭的时刻。
输入
第一行一个整数N,代表总共有N个人。 以下N行,每行两个整数 Ai,Bi。依次代表第i个人的打饭时间和吃饭时间。
输出
一个整数T,代表所有人吃完饭的最早时刻。
样例输入[复制]
5
2 2
7 7
1 3
6 4
8 5
样例输出[复制]
17
提示
所有输入数据均为不超过200的正整数。
样例说明 方案如下: 窗口1: 窗口2: 7 7 1 3 6 4 8 5 2 2
标签
ZJOI2005
这道题其实一看我们知道要结合贪心,这个道理其实是跟烹调方案是一样的
烹调方案告诉我们贪心应该从两个相邻的元素来入手
那么这道题里面有一个条件是吃饭时间长的人应该先排在前面
证明:假设有两个人吃饭时间是ai,bi,aj,bj其中bi>bj
如果是i先打饭的话,最长的时间就是ai+bi+bj
反之就是bi+ai+aj
显然进行比较的话会发现前者更优,得证
然后就是一个dp过程(未完待续。。。)
code:
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #define N 1004 6 using namespace std; 7 struct node{ 8 int a,b; 9 }e[N]; 10 bool cmp(node a,node b){ 11 return a.b>b.b; 12 } 13 int sum[N]; 14 int f[205][40005]; 15 int main(){ 16 int n; 17 cin>>n; 18 for(int i=1;i<=n;i++) 19 cin>>e[i].a>>e[i].b; 20 sort(e+1,e+n+1,cmp); 21 for(int i=1;i<=n;i++) 22 sum[i]=sum[i-1]+e[i].a; 23 memset(f,0x3f3f3f3f,sizeof f); 24 f[0][0]=0; 25 for(int i=1;i<=n;i++){ 26 for(int j=0;j<=sum[i];j++){ 27 if(j>=e[i].a)f[i][j]=min(f[i][j],max(f[i-1][j-e[i].a],j+e[i].b)); 28 f[i][j]=min(f[i][j],max(f[i-1][j],sum[i]-j+e[i].b)); 29 } 30 } 31 int ans=2147483647; 32 for(int i=0;i<=sum[n];i++) 33 ans=min(ans,f[n][i]); 34 cout<<ans; 35 return 0; 36 }
额,还要补前面的题解,慢慢来
原文地址:https://www.cnblogs.com/saionjisekai/p/9683596.html