UVa 12099 The Bookcase - 动态规划



  题目大意 给定一些书,每个书有一个高度和宽度,然后将它们放到一个三层的书架里(要求每一层都不为空)。定义书架的大小为每层最大的高度和 乘 每层宽度和的最大值。求最小的书架大小。

  显然动态规划(直觉,没有为什么)。

  然后确定状态,f[i][j][k]表示正在考虑第i本书,第2层的宽度和为j,第3层的宽度和为k(这样第一层的宽度和就可以计算出来)最小的高度和。然后发现无处下手。。。难道要把所有高度记录下来?

  现在来考虑优化,最简单的一种就是去除无用、重复状态。

  step 1 >> 放书的顺序和结果关系大吗?

      显然不,所以为了更好地进行动态规划,决定现将所有书按照高度排序,这样每次放书的时候就判读放的那一层是否为空就能够进行快速的转移了。

  然后发现状态总数 70 * 2100 * 2100 似乎会TLE(假设UVa的机子没有cf的辣么快,刘汝佳的书上说这会MLE,但是UVa不测内存啊),继续考虑优化吧。(如果您用bfs记忆化搜索似乎也可以)

  step 2 >> 考虑第一层放了宽度总和为8的书,第二层放了总和为4的书,和第一层放了总和为4的书,第二层放了总和为8的书有差别吗?

      显然答案与此无关,但是在上面的动态规划中,如果我们认为这样的状态是相同的,那么它岂不是把同一个状态计算了4次?

      所以我们规定,第一层的书的宽度和大于等于第二层,第二层的书的宽度总和大于第三层,这样就可以减少状态总数。

  然后状态总数70 * 1050 * 700,似乎就差不多。刚开始想滚动一下,就写的bfs来dp。

Code

  1 /**
  2  * UVa
  3  * Problem#12099
  4  * Accepted
  5  * Time:90ms
  6  */
  7 #include <bits/stdc++.h>
  8 using namespace std;
  9 typedef bool boolean;
 10 const signed int inf = (signed)((1u << 31) - 1);
 11 #define smin(a, b) (a) = min((a), (b))
 12 #define max3(a, b, c) max((a), max((b), (c)))
 13
 14 typedef class Book {
 15     public:
 16         int w;
 17         int h;
 18
 19         Book(int w = 0, int h = 0):w(w), h(h) {        }
 20
 21         boolean operator < (Book b) const {
 22             if(h != b.h) return h > b.h;
 23             return w > b.w;
 24         }
 25 }Book;
 26
 27 typedef class Status {
 28     public:
 29         int stage;
 30         int w2;
 31         int w3;
 32
 33         Status(int stage = 0, int w2 = 0, int w3 = 0):stage(stage), w2(w2), w3(w3) {        }
 34 }Status;
 35
 36 int n;
 37 int res;
 38 Book *bs;
 39 int *sumw;
 40 inline void init() {
 41     scanf("%d", &n);
 42     res = inf;
 43     bs = new Book[(n + 1)];
 44     sumw = new int[(n + 1)];
 45     for(int i = 1; i <= n; i++)
 46         scanf("%d%d", &bs[i].h, &bs[i].w);
 47 }
 48
 49 inline int getW1(Status& s) {
 50     return sumw[s.stage] - s.w2 - s.w3;
 51 }
 52
 53 inline void fix(Status& s) {
 54     int w1 = getW1(s);
 55     int a[3] = {w1, s.w2, s.w3};
 56     sort(a, a + 3);
 57     s.w2 = a[1], s.w3 = a[0];
 58 }
 59
 60 int f[71][1060][710];
 61 queue<Status> que;
 62 inline void dp() {
 63     memset(f, 0x7f, sizeof(f[0]) * (n + 1));
 64     f[0][0][0] = 0;
 65     que.push(Status(0, 0, 0));
 66     while(!que.empty()) {
 67         Status e = que.front(), eu;
 68         que.pop();
 69 //        printf("f(%d, %d, %d, %d) = %d\n", e.stage, getW1(e), e.w2, e.w3, f[e.stage][e.w2][e.w3]);
 70         if(e.stage == n) {
 71             if(getW1(e) && e.w2 && e.w3)
 72                 smin(res, (max3(getW1(e), e.w2, e.w3)) * f[n][e.w2][e.w3]);
 73             continue;
 74         }
 75
 76         eu = Status(e.stage + 1, e.w2, e.w3);
 77         fix(eu);
 78         if(f[eu.stage][eu.w2][eu.w3] == 0x7f7f7f7f)
 79             que.push(eu);
 80         smin(f[eu.stage][eu.w2][eu.w3], f[e.stage][e.w2][e.w3] + ((getW1(e)) ? (0) : (bs[eu.stage].h)));
 81
 82         eu = Status(e.stage + 1, e.w2 + bs[e.stage + 1].w, e.w3);
 83         fix(eu);
 84         if(f[eu.stage][eu.w2][eu.w3] == 0x7f7f7f7f)
 85             que.push(eu);
 86         smin(f[eu.stage][eu.w2][eu.w3], f[e.stage][e.w2][e.w3] + ((e.w2) ? (0) : (bs[eu.stage].h)));
 87
 88         eu = Status(e.stage + 1, e.w2, e.w3 + bs[e.stage + 1].w);
 89         fix(eu);
 90         if(f[eu.stage][eu.w2][eu.w3] == 0x7f7f7f7f)
 91             que.push(eu);
 92         smin(f[eu.stage][eu.w2][eu.w3], f[e.stage][e.w2][e.w3] + ((e.w3) ? (0) : (bs[eu.stage].h)));
 93     }
 94 }
 95
 96 inline void solve() {
 97     sort(bs + 1, bs + n + 1);
 98     sumw[0] = 0;
 99     for(int i = 1; i <= n; i++)
100         sumw[i] = sumw[i - 1] + bs[i].w;
101     dp();
102     printf("%d\n", res);
103 }
104
105 inline void clear() {
106     delete[] bs;
107 }
108
109 int T;
110 int main() {
111     scanf("%d", &T);
112     while(T--) {
113         init();
114         solve();
115         clear();
116     }
117     return 0;
118 }
时间: 2024-10-10 01:06:52

UVa 12099 The Bookcase - 动态规划的相关文章

UVA - 12099 The Bookcase

No wonder the old bookcase caved under the massive piles of books Tom had stacked on it. He had better build a new one, this time large enough to hold all of his books. Tom finds it practical to have the books close at hand when he works at his desk.

UVa 12099 The Bookcase (DP)

题意:有 n 本书,每本书有一个高度和宽度,然后让你制作一个3层的书架,可以放下所有的书,并且要高*宽尽量小. 析:先把所有的书按高度进行排序,然后dp[i][j][k] 表示 前 i 本书,第二 层的宽度是 j,第三层的宽度是 k,第二层和第三层的高度最小,首先我们可以先最高的那本书放到第一层,那么这一层的高度就确定了,同理,在放第二层和第三层的时候,如果是第一本书,那么这一层的高度就已经确定了,为什么不表示第一层的宽度呢,因为总宽度是确定的,如果第二层的宽度和第三层的宽度知道了,那么第一层也

【暑假】[深入动态规划]UVa 10618 The Bookcase

UVa 12099  The Bookcase 题目: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=42067 思路:   将n本书分配到三层,使得形成的书架w*h最小 提前将书籍按照高度排序,因为无论第一本书(最高的书)无论放在那一层都会被考虑到,所以规定将它放在第一层,且第二层比第三层高. 因为从大到小排序的关系,只要jk==0那么新加入的书i就是该层的高度,否则高度不变. 设d[i][j][k]表示考虑过i本书第二

uva 116 - Unidirectional TSP (动态规划)

第一次做动规题目,以下均为个人理解以及个人方法,状态转移方程以及状态的定义也是根据个人理解,请过路大神指教. 状态:每一列的每一个数[ i ][ j ]都是一个状态: 然后定义状态[ i ][ j ]的指标函数d[ i ][ j ]为从[ i ][ j ]向右出发的可以得到的最小的整数和: 状态转移方程:d[ i ][ j ]=min(d[ i+1 ][ j+1 ][ i-1 ][ j+1 ][ i ][ j+1 ])+a[ i ][ j ]; 其中a[ i ][ j ]为当前位置的数值: 然后

UVa 1626 Brackets sequence (动态规划)

题意:用最少的括号将给定的字符串匹配,输出最优解.可能有空行. 思路:dp. dp[i][j]表示将区间i,j之间的字符串匹配需要的最少括号数,那么 如果区间左边是(或[,表示可以和右边的字符串匹配,枚举中间断点k,如果str[i]==str[k]则dp[i][j]=min(dp[i][j],dp[i+1][k-1]+dp[k+1][j])表示不需要加入新的括号,也可以插入新的括号则dp[i][j]=min(dp[i][j],dp[i+1][k]+dp[k+1][j]+1). 如果区间最左边字符

UVA - 10003 Cutting Sticks(动态规划)

#include<iostream> #include<cstring> using namespace std; const int maxn = 50 + 3; int l, n; int c[maxn]; int dp[maxn][maxn]; int vis[maxn][maxn]; int solve2(int i, int j) { if(i == j - 1) return 0; if(vis[i][j]) return dp[i][j]; vis[i][j] = 1

[SinGuLaRiTy] 动态规划题目复习

[SinGuLaRiTy-1026] Copyright (c) SinGuLaRiTy 2017. All Rights Reserved. [UVA 1025] A Spy in the Metro 题目描述 特工玛利亚被送到S市执行一个特别危险的任务.她需要利用地铁完成他的任务,S市的地铁只有一条线路运行,所以并不复杂. 玛利亚有一个任务,现在的时间为0,她要从第一个站出发,并在最后一站的间谍碰头.玛利亚知道有一个强大的组织正在追踪她,她知道如果一直呆在一个车站,她会有很大的被抓的风险,躲

杭电ACM分类

杭电ACM分类: 1001 整数求和 水题1002 C语言实验题——两个数比较 水题1003 1.2.3.4.5... 简单题1004 渊子赛马 排序+贪心的方法归并1005 Hero In Maze 广度搜索1006 Redraiment猜想 数论:容斥定理1007 童年生活二三事 递推题1008 University 简单hash1009 目标柏林 简单模拟题1010 Rails 模拟题(堆栈)1011 Box of Bricks 简单题1012 IMMEDIATE DECODABILITY

【转】对于杭电OJ题目的分类

[好像博客园不能直接转载,所以我复制过来了..] 1001 整数求和 水题1002 C语言实验题——两个数比较 水题1003 1.2.3.4.5... 简单题1004 渊子赛马 排序+贪心的方法归并1005 Hero In Maze 广度搜索1006 Redraiment猜想 数论:容斥定理1007 童年生活二三事 递推题1008 University 简单hash1009 目标柏林 简单模拟题1010 Rails 模拟题(堆栈)1011 Box of Bricks 简单题1012 IMMEDI