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
/**
* 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 - 动态规划的更多相关文章
- UVA - 12099 The Bookcase
No wonder the old bookcase caved under the massive piles of books Tom had stacked on it. He had bett ...
- UVa 12099 The Bookcase (DP)
题意:有 n 本书,每本书有一个高度和宽度,然后让你制作一个3层的书架,可以放下所有的书,并且要高*宽尽量小. 析:先把所有的书按高度进行排序,然后dp[i][j][k] 表示 前 i 本书,第二 层 ...
- 【暑假】[深入动态规划]UVa 10618 The Bookcase
UVa 12099 The Bookcase 题目: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=42067 思路: ...
- UVa 1626 Brackets sequence (动态规划)
题意:用最少的括号将给定的字符串匹配,输出最优解.可能有空行. 思路:dp. dp[i][j]表示将区间i,j之间的字符串匹配需要的最少括号数,那么 如果区间左边是(或[,表示可以和右边的字符串匹配, ...
- 紫书 例题 9-2 UVa 437 ( DAG的动态规划)
很明显可以根据放不放建边,然后最一遍最长路即是答案 DAG上的动态规划就是根据题目中的二元关系来建一个 DAG,然后跑一遍最长路和最短路就是答案,可以用记忆化搜索的方式来实现 细节:(1)注意初始化数 ...
- UVA - 11468 (AC自动机+动态规划)
建立AC自动机,把AC自动机当做一张图,在上面跑L个节点就行了. 参考了刘汝佳的代码,发现可能有一个潜在的Bug--如果模式串中出现了没有指定的字符,AC自动机可能会建立出错. 提供一组关于这个BUG ...
- uva 116 - Unidirectional TSP (动态规划)
第一次做动规题目,下面均为个人理解以及个人方法,状态转移方程以及状态的定义也是依据个人理解.请过路大神不吝赐教. 状态:每一列的每个数[ i ][ j ]都是一个状态: 然后定义状态[ i ][ j ...
- 紫书 例题 9-1 UVa 1025 ( DAG的动态规划)
影响到状态的只有时间和在哪个车站(空间),所以可以设f[i][j]是时刻i的时候在第j个车站的最少等待时间 因为题目中的等待时间显然是在0时刻1车站,所以答案为f[0][1],那么就提醒我们从大推到小 ...
- [SinGuLaRiTy] 动态规划题目复习
[SinGuLaRiTy-1026] Copyright (c) SinGuLaRiTy 2017. All Rights Reserved. [UVA 1025] A Spy in the Metr ...
随机推荐
- selenium元素高亮显示
selenium元素高亮显示: 采用js注入的方式,通过更改元素样式来实现. border:2px 边框 solid red 红色 def hightlight(self,element): &qu ...
- Beta冲刺阶段3.0
1. 提供当天站立式会议照片一张 2. 每个人的工作 (有work item 的ID) 成员 昨天已完成的工作 今天计划完成的工作 工作中遇到的困难 具体贡献 郑晓丽 完成"我的活动&quo ...
- [1]windows 内核情景分析---说明
本文说明:这一系列文章(笔记)是在看雪里面下载word文档,现转帖出来,希望更多的人能看到并分享,感谢原作者的分享精神. 说明 本文结合<Windows内核情景分析>(毛德操著).< ...
- 6.Daemon线程
1.如下代码: package com.bawei.multithread; public class Recursive { private static int counter = 0; publ ...
- python -- 判断给定的参数是否是地理位置的经度和纬度
例子: coordinates = "2.3,-8ui" 无效地理位置 coordinates = "2.3,-8i" 有效地理位置 方法一:使用try...e ...
- UIView常见方法
- (void)addSubview:(UIView *)view; 添加一个子控件view - (void)removeFromSuperview; 从父控件中移除 - (UIView *)vi ...
- Sitecore CMS中的项目如何配置帮助文本
如何在Sitecore CMS中的项目上配置帮助文本. 所有Sitecore项目都有长短描述字段,以及“帮助链接”字段.这些字段有助于向内容编辑者提供其他信息.这对于很少编辑的项目和字段尤其重要,因为 ...
- 如何在Sitecore CMS中创建项目
从功能区 打开Sitecore的内容编辑器,选择内容树中的项目.创建的项目将作为所选项目的子项添加. Sitecore 8显示所选的Home项目 Sitecore 6和7显示所选的Home项目 功能区 ...
- python操作Mysql数据库示例
python库:pymysql 安装:install pymysql.mysql数据库 一.连接数据库.创建speder库.查询版本. import pymysql ##链接数据库 db = pymy ...
- flask模板应用-javaScript和CSS中jinja2
当程序逐渐变大时,很多时候我们需要在javaScript和CSS代码中使用jinja2提供的变量值,甚至是控制语句.比如,通过传入模板的theme_color变量来为页面设置主题色彩,或是根据用户是否 ...