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

  考虑动态规划。

  然后确定状态,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. 24.form表单提交的六种方式

    form表单提交方式 1.无刷新页面提交表单 表单可实现无刷新页面提交,无需页面跳转,如下,通过一个隐藏的iframe实现,form表单的target设置为iframe的name名称,form提交目标 ...

  2. jQuery-图片放大镜

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  3. install apache-activemq

    进入bin/linux-x86-64下 cd apache-activemq-5.14.1/bin/linux-x86-64/ 启动 ./activemq start 五.启动成功后,访问 activ ...

  4. <meta>标签中,X-UA-Compatible和IE=Edge,chrome=1的作用

    用来指定浏览器优先以什么模式来渲染页面,ie=edge表示以最高版本内核渲染,ie=8表示以id8内核渲染页面,此外还有ie=9.id=10等. 而chrome=1意思是,优先以chrome内核来渲染 ...

  5. 总结我在huawei matebook D 2018版中安装archlinux的过程

    1.首先当然是准备一个启动U盘.按理说UEFI启动方式,只要将ISO镜像中的文件copy到U盘根目录即可,可以实际用的时候虽然能启动,但是进入live的时候会有些问题,所以老老实实用UltraISO ...

  6. 更换tomcat运行日志目录

    1.在tomcat安装文件夹的bin目录下,修改catalina.sh,改变catalina.out的输出目录 CATALINA_OUT="$CATALINA_BASE"/logs ...

  7. C#基础知识整理

    年时,北风吹雁雪纷纷,一条秋裤冻上头.冷的连手都懒得动,就随便翻翻书,也没有更新博客,如今年已过,开始投入到正常的工作状态中,趁现在需求还没有来,把C#基础知识梳理一下,其实一直以来就想这样做的,对于 ...

  8. django2.0 路由规则

    Django2.0中URL的路由机制 路由是关联url及其处理函数关系的过程.Django的url路由配置在settings.py文件中ROOT_URLCONF变量指定全局路由文件名称. Django ...

  9. golang学习笔记6 beego项目路由设置

    golang学习笔记5 beego项目路由设置 前面我们已经创建了 beego 项目,而且我们也看到它已经运行起来了,那么是如何运行起来的呢?让我们从入口文件先分析起来吧: package main ...

  10. javascript 链式写法

    熟悉Jquery的同学都知道,它对dom的操作基本都链式调用的写法,这种给人感觉就是很简洁,易懂,而且最大的好处就是避免多次重复使用一个对象变量. 链式的实现方式:链式操作是在对象的方法中通过最后返回 ...