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

  考虑动态规划。

  然后确定状态,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

 /**
* UVa
* Problem#12099
* Accepted
* Time:90ms
*/
#include <bits/stdc++.h>
using namespace std;
typedef bool boolean;
const signed int inf = (signed)((1u << ) - );
#define smin(a, b) (a) = min((a), (b))
#define max3(a, b, c) max((a), max((b), (c))) typedef class Book {
public:
int w;
int h; Book(int w = , int h = ):w(w), h(h) { } boolean operator < (Book b) const {
if(h != b.h) return h > b.h;
return w > b.w;
}
}Book; typedef class Status {
public:
int stage;
int w2;
int w3; Status(int stage = , int w2 = , int w3 = ):stage(stage), w2(w2), w3(w3) { }
}Status; int n;
int res;
Book *bs;
int *sumw;
inline void init() {
scanf("%d", &n);
res = inf;
bs = new Book[(n + )];
sumw = new int[(n + )];
for(int i = ; i <= n; i++)
scanf("%d%d", &bs[i].h, &bs[i].w);
} inline int getW1(Status& s) {
return sumw[s.stage] - s.w2 - s.w3;
} inline void fix(Status& s) {
int w1 = getW1(s);
int a[] = {w1, s.w2, s.w3};
sort(a, a + );
s.w2 = a[], s.w3 = a[];
} int f[][][];
queue<Status> que;
inline void dp() {
memset(f, 0x7f, sizeof(f[]) * (n + ));
f[][][] = ;
que.push(Status(, , ));
while(!que.empty()) {
Status e = que.front(), eu;
que.pop();
// printf("f(%d, %d, %d, %d) = %d\n", e.stage, getW1(e), e.w2, e.w3, f[e.stage][e.w2][e.w3]);
if(e.stage == n) {
if(getW1(e) && e.w2 && e.w3)
smin(res, (max3(getW1(e), e.w2, e.w3)) * f[n][e.w2][e.w3]);
continue;
} eu = Status(e.stage + , e.w2, e.w3);
fix(eu);
if(f[eu.stage][eu.w2][eu.w3] == 0x7f7f7f7f)
que.push(eu);
smin(f[eu.stage][eu.w2][eu.w3], f[e.stage][e.w2][e.w3] + ((getW1(e)) ? () : (bs[eu.stage].h))); eu = Status(e.stage + , e.w2 + bs[e.stage + ].w, e.w3);
fix(eu);
if(f[eu.stage][eu.w2][eu.w3] == 0x7f7f7f7f)
que.push(eu);
smin(f[eu.stage][eu.w2][eu.w3], f[e.stage][e.w2][e.w3] + ((e.w2) ? () : (bs[eu.stage].h))); eu = Status(e.stage + , e.w2, e.w3 + bs[e.stage + ].w);
fix(eu);
if(f[eu.stage][eu.w2][eu.w3] == 0x7f7f7f7f)
que.push(eu);
smin(f[eu.stage][eu.w2][eu.w3], f[e.stage][e.w2][e.w3] + ((e.w3) ? () : (bs[eu.stage].h)));
}
} inline void solve() {
sort(bs + , bs + n + );
sumw[] = ;
for(int i = ; i <= n; i++)
sumw[i] = sumw[i - ] + bs[i].w;
dp();
printf("%d\n", res);
} inline void clear() {
delete[] bs;
} int T;
int main() {
scanf("%d", &T);
while(T--) {
init();
solve();
clear();
}
return ;
}

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

  1. UVA - 12099 The Bookcase

    No wonder the old bookcase caved under the massive piles of books Tom had stacked on it. He had bett ...

  2. UVa 12099 The Bookcase (DP)

    题意:有 n 本书,每本书有一个高度和宽度,然后让你制作一个3层的书架,可以放下所有的书,并且要高*宽尽量小. 析:先把所有的书按高度进行排序,然后dp[i][j][k] 表示 前 i 本书,第二 层 ...

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

    UVa 12099  The Bookcase 题目: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=42067 思路:    ...

  4. UVa 1626 Brackets sequence (动态规划)

    题意:用最少的括号将给定的字符串匹配,输出最优解.可能有空行. 思路:dp. dp[i][j]表示将区间i,j之间的字符串匹配需要的最少括号数,那么 如果区间左边是(或[,表示可以和右边的字符串匹配, ...

  5. 紫书 例题 9-2 UVa 437 ( DAG的动态规划)

    很明显可以根据放不放建边,然后最一遍最长路即是答案 DAG上的动态规划就是根据题目中的二元关系来建一个 DAG,然后跑一遍最长路和最短路就是答案,可以用记忆化搜索的方式来实现 细节:(1)注意初始化数 ...

  6. UVA - 11468 (AC自动机+动态规划)

    建立AC自动机,把AC自动机当做一张图,在上面跑L个节点就行了. 参考了刘汝佳的代码,发现可能有一个潜在的Bug--如果模式串中出现了没有指定的字符,AC自动机可能会建立出错. 提供一组关于这个BUG ...

  7. uva 116 - Unidirectional TSP (动态规划)

    第一次做动规题目,下面均为个人理解以及个人方法,状态转移方程以及状态的定义也是依据个人理解.请过路大神不吝赐教. 状态:每一列的每个数[ i ][ j ]都是一个状态: 然后定义状态[ i ][ j ...

  8. 紫书 例题 9-1 UVa 1025 ( DAG的动态规划)

    影响到状态的只有时间和在哪个车站(空间),所以可以设f[i][j]是时刻i的时候在第j个车站的最少等待时间 因为题目中的等待时间显然是在0时刻1车站,所以答案为f[0][1],那么就提醒我们从大推到小 ...

  9. [SinGuLaRiTy] 动态规划题目复习

    [SinGuLaRiTy-1026] Copyright (c) SinGuLaRiTy 2017. All Rights Reserved. [UVA 1025] A Spy in the Metr ...

随机推荐

  1. /usr/lib/python2.7/site-packages/requests/__init__.py:91: RequestsDependencyWarning: urllib3 (1.22) or chardet (2.2.1) doesn't match a supported version!

    /usr/lib/python2.7/site-packages/requests/ __init__.py:91: RequestsDependencyWarning: urllib3(1.22)或 ...

  2. java 之多线程

    多线程基本概念_程序_线程 1.1程序.进程.线程 程序:Program是一个指令的集合 进程:Process(正在执行中的程序)是一个静态的概念.进程是程序的一次静态执行过程,占用特定的地址空间.每 ...

  3. Unity shader学习之屏幕后期处理效果之Bloom效果

    Bloom特效是游戏中常见的一种屏幕效果.这种特效可以模拟真实摄像机的一种图像效果,它让画面中较亮的区域“扩散”到周围的区域中,造成一种朦胧的效果. Bloom的实现原理很简单,首先根据一个阈值提取出 ...

  4. ReentrantLock源码(二)

    一.ReentrantLock类中的方法解读. 1.lock方法.实现了接口Lock中的lock方法.这里实际上是调用了sync成员变量的lock方法来实现.所以取决于sync的实现. 2.unloc ...

  5. Yii restful api跨域

    问题:NO 'Access-Control_Allow-Origin' header is present on the requested resource. 解决方案 <?php names ...

  6. arm cortex-m0plus源码学习(三)GPIO

    概述: Cortex-m0的integration_kit提供三个GPIO接口,其中GPIO0传输到外部供用户使用,为EXTGPIO:GPIO1是内核自己的信号,不能乱改,会崩掉:GPIO2是一些中断 ...

  7. Presto 学习参考资料

    Presto 文档资料: 0.1版:Presto 0.100 Documentation 0.213版:Presto 0.213 Documentation 阿里云 presto 学习资料:https ...

  8. Git相关整理以及学习

    1.取消还未进入暂存区的修改 git checkout + 文件名 2.取消已经进入暂存区但是还未提交的修改 git reset HEAD + 文件名 3.清理在远程仓库已经被删除的本地分支 git ...

  9. go语言,golang学习笔记3 用命令下载框架报错问题解决 设置环境变量

    go语言,golang学习笔记3 用命令下载框架报错问题解决 设置环境变量 下载安装:go get github.com/astaxie/beego 首页 - beego: 简约 & 强大并存 ...

  10. java.lang.RuntimeException: can not run elasticsearch as root

    忘写了一个错误: [o.e.b.ElasticsearchUncaughtExceptionHandler] [] uncaught exception in thread [main] org.el ...