卧薪尝胆,厚积薄发。
ZJOI2005 午餐
Date: Wed Sep 19 10:48:13 CST 2018 In Category: NoCategory

Description:

每个人有打饭时间和吃饭时间,有两个窗口,最小化最后一个人吃完饭的时间。
$1\le n \le 200,1\le a,b\le 200$

Solution:

首先我们肯定贪心的把吃饭时间长的人放在前面,所以先按吃饭时间排序,然后 $DP$ , $f[i][j]$ 表示到了第 $i$ 个人第一个窗口等待时间为 $j$ 的所有人都吃完饭的最小时间,第二个窗口的时间可以计算出来,所以不用表示在状态里,然后枚举当前这个人在哪个窗口吃饭,用这个窗口的值取 $min$ 就行了。

Code:


#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
int n;
#define MAXN 210
int f[MAXN][MAXN * MAXN];
struct peo
{
int a,b;
}p[MAXN];
bool cmp_b(peo x,peo y){return x.b > y.b;}
int sum[MAXN];
int main()
{
scanf("%d",&n);
for(int i = 1;i <= n;++i)
scanf("%d%d",&p[i].a,&p[i].b);
sort(p + 1,p + 1 + n,cmp_b);
for(int i = 1;i <= n;++i)
sum[i] = sum[i - 1] + p[i].a;
memset(f,0x3f,sizeof(f));
f[0][0] = 0;
for(int i = 1;i <= n;++i)
{
for(int j = 1;j <= sum[i];++j)
{
if(j >= p[i].a)f[i][j] = min(f[i][j],max(f[i - 1][j - p[i].a],j + p[i].b));
f[i][j] = min(f[i][j],max(f[i - 1][j],sum[i] - j + p[i].b));
}
}
int ans = 0x3f3f3f3f;
for(int i = 1;i <= sum[n];++i)
{
ans = min(ans,f[n][i]);
}
cout << ans << endl;
return 0;
}
Copyright © 2020 wjh15101051
ღゝ◡╹)ノ♡