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 ...
随机推荐
- unity3d-知识汇总
itween下载 http://www.youkexueyuan.com/exp_show/1147.html 代码修改精灵图片的透明度 UIBp.GetComponent<Image>( ...
- php开启pdo扩展
在Windows环境下php 5.1以上版本中,pdo和主要数据库的驱动同php一起作为扩展发布,要激活它们只需要简单地编辑php.ini文件. 打开php.ini配置文件,找到extension=p ...
- nodejs连接数据库的增删改查
连接数据库后需要用代码操作的是,传入mysql语句,和参数,然后就是回调了 新增 // 新增 app.post('/process_post', urlencodedParser, function ...
- activity bj draw 流程图
- DX9 DirectX键盘控制程序 代码
// @time: 2012.3.26 // @author: jadeshu // des: DirectX键盘控制程序 #include <Windows.h> #include &l ...
- vs2013未找到与约束匹配的导出
解决方法: 1.关闭VS: 2.去C:/Users/<your users name>/AppData/Local/Microsoft/VisualStudio/12.0/Componen ...
- Java多线程-----Thread常用方法
1.public Thread(Runnable target,String name) 创建一个有名称的线程对象 package com.thread.mothed; public class Th ...
- vue-cli 脚手架搭建
1,下载node.js node.js 集成npm 管理器 2,打开命令行工具(win+R) node -v npm -v 出现对应版本号,则安装完成 3,配置代理信息 详见代理设定:https:// ...
- mysql 创建用户,删除用户,增加权限
1,查询mysql 数据库已经存在的用户: SELECT USER,HOST FROM MYSQL.USER; 2,创建mysql 用户: '; USERNAME:用户名 HOST:主机,PASSWO ...
- hi3516a arm-hisiv300-linux-gcc jrtplib交叉编译
1.进入JThread-1.2.1文件夹 2../configure --prefix=/home/suxuandong/Documents/qth264/hi3516/jrtpjthreadhisi ...