本文主要是介绍[DP][贪心]午餐,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
题目描述
上午的训练结束了,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的正整数。
分析
我们想一想,可得一个简单的贪心思想:吃饭时间长的,先排队
所以按这个排个序先
然后我们设fi表示队列1排队时间为i的时候的总时间
易得:
k=1~n
fi+ak=min{max(fi,i+ak+bk) (当k加入队列1时)
fi=max(fi,sum[a1~i -j+bk) (当k加入队列2时)
只要处理一个前缀和就行
#include <iostream>
#include <cstdio>
#include <algorithm>
#define rep(i,a,b) for (i=a;i<=b;i++)
using namespace std;
int n;
struct M
{int a,b;
}a[201];
int s[201],sut;
int f[40001];
int ans;
int i,j;
bool cmp(M a,M b)
{return a.b>b.b;
}
int main()
{scanf("%d",&n);rep(i,1,n)scanf("%d%d",&a[i].a,&a[i].b);sort(a+1,a+n+1,cmp);rep(i,1,40000) f[i]=2147483647;rep(i,1,n)s[i]=a[i].a+s[i-1];rep(i,1,n){for (j=sut;j>=0;j--){f[j+a[i].a]=min(f[j+a[i].a],max(f[j],j+a[i].a+a[i].b));f[j]=max(f[j],s[i]-j+a[i].b);}sut+=a[i].a;}ans=2147483647;rep(i,1,sut)ans=min(ans,f[i]);printf("%d",ans);
}
这篇关于[DP][贪心]午餐的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!