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

  考虑动态规划。

  然后确定状态,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. 实验验证sys和system用户全库导出的区别

    我们在做逻辑数据泵全库导出的时候,有两种流行的写法,一种是sys用户导出,一种是使用system用户导出. 现在想知道二者之间有什么区别?实验验证之前不妨先思考一下: sys和system用户的权限区 ...

  2. 本地计算机上的SQLServer(MSSQLSERVER)服务启动后停止,某些服务在未由其他服务或程序使用时将自动停止

    SQLServer的服务启动问题: 本地计算机上的SQLServer(MSSQLSERVER)服务启动后停止,某些服务在未由其他服务或程序使用时将自动停止 出现这个问题导致无法启动SQLServer服 ...

  3. PHP数据库环境配置

    wamp环境   w是windows系统       a是Apache(服务器管理软件)      m是MySQL(数据库)    p是PHP wamp正常情况下是绿色的可以正常使用 黄色和红色不能使 ...

  4. 三 js语句

    /** * Created by Administrator on 2017/12/24. * 1.顺序语句 * 2.选择语句 if else swtich case * 3.循环语句 for whi ...

  5. windows假装更新升级

    http://fakeupdate.net/ 进入这个网站,选择一款系统界面,按F11进去全屏 比较有趣

  6. 向SQL Server中导入Excel的数据

    1.  手动界面导入Excel数据 同 https://jingyan.baidu.com/article/ce09321b9a0e252bff858ff9.html 首先打开并登陆sql serve ...

  7. python 数据序列化(json、pickle、shelve)

    本来要查一下json系列化自定义对象的一个问题,然后发现这篇博客(https://www.cnblogs.com/yyds/p/6563608.html)很全面,感谢作者,关于python序列化的知识 ...

  8. Hive 的排名和跨行 窗口函数及其使用

    一.排序&去重分析 row_number() over(partititon by col1 order by col2) as rn 也可以用 row_number() over(distr ...

  9. 转:【专题五】TCP编程

    前言 前面专题的例子都是基于应用层上的HTTP协议的介绍, 现在本专题来介绍下传输层协议——TCP协议,主要介绍下TCP协议的工作过程和基于TCP协议的一个简单的通信程序,下面就开始本专题的正文了. ...

  10. px-pt-dp-rem像素单位的换算问题

    px-pt-dp-rem像素单位的换算问题 dp 的意思从 MDPI 到 XXXHDPI 每单位物理尺寸的像素数越来越大.也就是说 mdpi 时 1dp = 1pxxxxhdpi 时 1dp = 4p ...