BZOJ_2021
首先一个贪心的思路就是,如果需要大奶酪,那么一定把大的放在上面,而且是把高度最小的大奶酪放在最上面。因此我们可以现将奶酪排个序,把小奶酪放下面,大奶酪放上面,而且大奶酪较矮的放在最上面。
接着考虑放奶酪的决策,如果不用大奶酪的话自然就是一个裸的背包问题,如果用大奶酪就会涉及到一个问题,就是最上面的奶酪是原高,其余的都是原高的4/5,这时可以多加一个bit表示现在奶酪是不是已经“封顶”了,在“封顶”之前高度都按4/5算,“封顶”时按原高算即可。
#include<stdio.h> #include<string.h> #include<algorithm> #define MAXN 110 #define MAXT 1010 int N, T, K, f[MAXT][2]; struct St { int v, h; bool operator < (const St &t) const { if((h < K && t.h < K) || (h >= K && t.h >= K)) return h > t.h; return h < K; } }st[MAXN]; void init() { for(int i = 0; i < N; i ++) scanf("%d%d", &st[i].v, &st[i].h); std::sort(st, st + N); } void solve() { memset(f, 0, sizeof(f)); int ans = 0; for(int i = 0; i < N && st[i].h < K; i ++) for(int j = st[i].h; j <= T; j ++) f[j][0] = std::max(f[j][0], f[j - st[i].h][0] + st[i].v); ans = std::max(ans, f[T][0]); for(int i = 0; i < N; i ++) { if(st[i].h >= K) { for(int j = st[i].h / 5 * 4; j <= T; j ++) f[j][0] = std::max(f[j][0], f[j - st[i].h / 5 * 4][0] + st[i].v); for(int j = st[i].h; j <= T; j ++) f[j][1] = std::max(f[j][1], f[j - st[i].h][0] + st[i].v); } else { for(int j = st[i].h / 5 * 4; j <= T; j ++) f[j][0] = std::max(f[j][0], f[j - st[i].h / 5 * 4][0] + st[i].v); } } ans = std::max(ans, f[T][1]); printf("%d\n", ans); } int main() { while(scanf("%d%d%d", &N, &T, &K) == 3) { init(); solve(); } return 0; }