Luogu 2577[ZJOI2005]午餐

Solution

啊。。。 我太菜了唔

不看题解是不可能的, 这辈子都不可能的。

首先一个队伍中排队轮到某个人的时间是递增的, 又要加上吃饭时间, 所以只能使吃饭时间递减, 才能满足最优,于是以吃饭时间为关键字排序

然后定义数组 $f[i][j]$ 为前$i$个,第一个队伍要排$j$分钟时, 前$i$个人最晚吃完饭的时间。我们还可以很快的算出第二个队伍要排 $sum[i] - j$分钟。

然后就可以进行简单的转移。

 

dp水平还需提高ouo

Code

 1 #include<cstring>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #define rd read()
 5 #define rep(i,a,b) for(register int i = (a); i <= (b); ++i)
 6 #define per(i,a,b) for(register int i = (a); i >= (b); --i)
 7 using namespace std;
 8 
 9 const int N = 300;
10 
11 int n, f[N][N * N], sum[N], ans = ~0U >> 2;
12 
13 struct node {
14     int eat, wait;
15 }a[N];
16 
17 int read() {
18     int X = 0, p = 1; char c = getchar();
19     for(; c > '9' || c < '0'; c = getchar()) if(c == '-') p = -1;
20     for(; c >= '0' && c <= '9'; c = getchar()) X = X * 10 + c - '0';
21     return X * p;
22 }
23 
24 int cmp(const node &A, const node &B) {
25     return A.eat == B.eat ? A.wait < B.wait : A.eat > B.eat;
26 }
27 
28 int main()
29 {
30     n = rd;
31     rep(i, 1, n) {
32         a[i].wait = rd;
33         a[i].eat = rd;
34     }
35     sort(a+1, a+1+n, cmp);
36     rep(i, 1, n) sum[i] = sum[i - 1] + a[i].wait;
37     memset(f, 63, sizeof(f));
38     f[0][0] = 0;
39     rep(i, 1, n) rep(j, 0, sum[i]) {
40         f[i][j] = min(f[i][j], max(f[i - 1][j], a[i].eat + sum[i] - j));
41         if(j >= a[i].wait) f[i][j] = min(f[i][j], max(f[i - 1][j - a[i].wait], a[i].eat + j));
42     }
43     rep(i, 0, sum[n]) ans = min(ans, f[n][i]);
44     printf("%d
", ans);
45 }
View Code
原文地址:https://www.cnblogs.com/cychester/p/9578456.html