The Bookcase
https://odzkskevi.qnssl.com/31465a17250189570dad37924cda0d26?v=1508622471
【题解】
。。。紫书上第二个优化不可信啊!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
去了第二个优化写的滚动数组!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
各种智障错!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
调了少说五六个小时!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
气啊!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
这里规定第一层高度 >= 第二层高度 >= 第三层高度
不难发现交换任意两层是一样的,所以这样规定无可厚非
dp状态和转移见程序
1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 #include <cstdlib> 5 #include <cstring> 6 #include <vector> 7 #define min(a, b) ((a) < (b) ? (a) : (b)) 8 #define max(a, b) ((a) > (b) ? (a) : (b)) 9 10 inline void swap(int &a, int &b) 11 { 12 long long tmp = a;a = b;b = tmp; 13 } 14 15 inline void read(int& x) 16 { 17 x = 0;char ch = getchar(), c = ch; 18 while(ch < '0' || ch > '9')c = ch, ch = getchar(); 19 while(ch <= '9' && ch >= '0')x = x * 10 + ch - '0', ch = getchar(); 20 } 21 22 const int INF = 0x3f3f3f3f; 23 const int MAXN = 80; 24 const int MAXJ = 2500; 25 const int MAXK = 2500; 26 27 int dp[2][MAXK + 10][MAXK + 10], n, sum[MAXN + 10], t, ans; 28 29 struct Node 30 { 31 int h,w; 32 }node[MAXN + 10]; 33 34 int cmp(Node a, Node b) 35 { 36 return a.h == b.h ? a.w < b.w : a.h > b.h; 37 } 38 39 int main() 40 { 41 read(t); 42 for(;t;--t) 43 { 44 read(n); 45 ans = INF; 46 for(register int i = 1;i <= n;++ i) read(node[i].h), read(node[i].w); 47 std::sort(node + 1, node + 1 + n, cmp); 48 for(register int i = 1;i <= n;++ i)sum[i] = sum[i - 1] + node[i].w; 49 //dp[i][j][k]表示前i本书,第二层宽j,第三层宽k,第一层宽sum[i] - j - k,高度h1 <= h2 <= h3的最小总高度 50 dp[0][0][0] = 0; 51 memset(dp[1], 0x3f, sizeof(dp[1])); 52 dp[1][0][0] = node[1].h; 53 int now = 1; 54 for(register int i = 1;i < n;++ i) 55 { 56 memset(dp[now ^ 1], 0x3f, sizeof(dp[now ^ 1])); 57 for(register int j = 0;j <= sum[n];++ j) 58 { 59 if(j > sum[i + 1] - sum[1])break; 60 for(register int k = 0;k <= sum[n];++ k) 61 { 62 if(j + k > sum[i + 1] - sum[1])break; 63 //放在第一层 64 dp[now ^ 1][j][k] = min(dp[now ^ 1][j][k], dp[now][j][k]); 65 //放在第二层 66 if(j + node[i + 1].w <= sum[i + 1]) 67 { 68 if(j == 0) dp[now ^ 1][j + node[i + 1].w][k] = min(dp[now ^ 1][j + node[i + 1].w][k], dp[now][j][k] + node[i + 1].h); 69 else dp[now ^ 1][j + node[i + 1].w][k] = min(dp[now ^ 1][j + node[i + 1].w][k], dp[now][j][k]); 70 } 71 //放在第三层 72 if(k + node[i + 1].w <= sum[i + 1] && j != 0) 73 { 74 if(k == 0) dp[now ^ 1][j][k + node[i + 1].w] = min(dp[now ^ 1][j][k + node[i + 1].w], dp[now][j][k] + node[i + 1].h); 75 else dp[now ^ 1][j][k + node[i + 1].w] = min(dp[now ^ 1][j][k + node[i + 1].w], dp[now][j][k]); 76 } 77 } 78 } 79 now ^= 1; 80 } 81 for(register int j = 1;j <= sum[n];++ j) 82 for(register int k = 1;k <= sum[n];++ k) 83 { 84 if(dp[now][j][k] >= INF)continue; 85 if(sum[n] - j - k < node[1].w)break; 86 ans = min(ans, dp[now][j][k] * max(j, max(k, sum[n] - j - k))); 87 } 88 printf("%d ", ans); 89 } 90 return 0; 91 }