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\n", ans); 45 }