题意:有 n 本书,每本书有一个高度和宽度,然后让你制作一个3层的书架,可以放下所有的书,并且要高*宽尽量小。

析:先把所有的书按高度进行排序,然后dp[i][j][k] 表示 前 i 本书,第二 层的宽度是 j,第三层的宽度是 k,第二层和第三层的高度最小,首先我们可以先最高的那本书放到第一层,那么这一层的高度就确定了,同理,在放第二层和第三层的时候,如果是第一本书,那么这一层的高度就已经确定了,为什么不表示第一层的宽度呢,因为总宽度是确定的,如果第二层的宽度和第三层的宽度知道了,那么第一层也就确定了。有了这些就可以进行状态转移了。注意不要转移无用的状态以降低时间复杂度。

有三种决策,1 放在第一层,dp[i+1][j][k] = min{ dp[i][j][k] }

2.放在第二层,那么又有两种情况,第一次放,还是不是第一次放

if(j == 0)  dp[i+1][j+w][k] = min{ dp[i][j][k] + h }

else  dp[i+1][j+w][k] = min{ dp[i][j][k] }

3.放在第三层,这一种和第二层一样。

代码如下:

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <cstring>
#include <set>
#include <queue>
#include <algorithm>
#include <vector>
#include <map>
#include <cctype>
#include <cmath>
#include <stack>
#include <sstream>
#include <list>
#include <assert.h>
#include <bitset>
#define debug() puts("++++");
#define gcd(a, b) __gcd(a, b)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define fi first
#define se second
#define pb push_back
#define sqr(x) ((x)*(x))
#define ms(a,b) memset(a, b, sizeof a)
#define sz size()
#define pu push_up
#define pd push_down
#define cl clear()
#define all 1,n,1
#define FOR(x,n) for(int i = (x); i < (n); ++i)
#define freopenr freopen("in.txt", "r", stdin)
#define freopenw freopen("out.txt", "w", stdout)
using namespace std; typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> P;
const int INF = 0x3f3f3f3f;
const double inf = 1e20;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int maxn = 200000 + 10;
const LL mod = 1e9 + 7;
const int dr[] = {-1, 0, 1, 0};
const int dc[] = {0, 1, 0, -1};
const char *de[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};
int n, m;
const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
inline bool is_in(int r, int c) {
return r > 0 && r <= n && c > 0 && c <= m;
} int dp[2][2105][2105];
struct Node{
int h, w;
bool operator < (const Node &p) const {
return h > p.h;
}
};
Node a[80];
int sum[maxn]; int main(){
int T; cin >> T;
while(T--){
scanf("%d", &n);
for(int i = 1; i <= n; ++i) scanf("%d %d", &a[i].h, &a[i].w);
sort(a + 1, a + n + 1);
for(int i = 2; i <= n; ++i) sum[i] = sum[i-1] + a[i].w;
int cnt = 0;
ms(dp[0], INF);
dp[0][0][0] = 0;
for(int i = 1; i < n; ++i, cnt ^= 1){
ms(dp[cnt^1], INF);
for(int j = 0; j <= sum[i]; ++j){
for(int k = 0; k <= sum[i]; ++k){
if(j + k > sum[i]) break;
if(dp[cnt][j][k] == INF) continue;
dp[cnt^1][j][k] = min(dp[cnt^1][j][k], dp[cnt][j][k]);
if(j == 0) dp[cnt^1][a[i+1].w][k] = min(dp[cnt^1][a[i+1].w][k], dp[cnt][j][k] + a[i+1].h);
else dp[cnt^1][j+a[i+1].w][k] = min(dp[cnt^1][j+a[i+1].w][k], dp[cnt][j][k]);
if(k == 0) dp[cnt^1][j][a[i+1].w] = min(dp[cnt^1][j][a[i+1].w], dp[cnt][j][k] + a[i+1].h);
else dp[cnt^1][j][k+a[i+1].w] = min(dp[cnt^1][j][k+a[i+1].w], dp[cnt][j][k]);
}
}
} int ans = INF;
for(int i = 0; i <= sum[n]; ++i)
for(int j = 0; j <= sum[n]; ++j){
if(i + j > sum[n]) break;
if(dp[cnt][i][j] == INF) continue;
if(i == 0 || j == 0) continue;
ans = min(ans, (dp[cnt][i][j] + a[1].h) * max(j, max(i, sum[n]-j-i+a[1].w)));
}
printf("%d\n", ans);
}
return 0;
}

  

UVa 12099 The Bookcase (DP)的更多相关文章

  1. UVa 12099 The Bookcase - 动态规划

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

  2. UVA - 12099 The Bookcase

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

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

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

  4. UVA.674 Coin Change (DP 完全背包)

    UVA.674 Coin Change (DP) 题意分析 有5种硬币, 面值分别为1.5.10.25.50,现在给出金额,问可以用多少种方式组成该面值. 每种硬币的数量是无限的.典型完全背包. 状态 ...

  5. uva 10817(数位dp)

    uva 10817(数位dp) 某校有m个教师和n个求职者,需讲授s个课程(1<=s<=8, 1<=m<=20, 1<=n<=100).已知每人的工资c(10000 ...

  6. UVA 11404 Palindromic Subsequence[DP LCS 打印]

    UVA - 11404 Palindromic Subsequence 题意:一个字符串,删去0个或多个字符,输出字典序最小且最长的回文字符串 不要求路径区间DP都可以做 然而要字典序最小 倒过来求L ...

  7. uva 10453 - Make Palindrome(dp)

    题目链接:10453 - Make Palindrome 题目大意:给出一个字符串,通过插入字符使得原字符串变成一个回文串,要求插入的字符个数最小,并且输出最后生成的回文串. 解题思路:和uva 10 ...

  8. uva 10671 - Grid Speed(dp)

    题目链接:uva 10671 - Grid Speed 题目大意:给出N,表示在一个N*N的网格中,每段路长L,如今给出h,v的限制速度,以及起始位置sx,sy,终止位置ex,ey,时间范围st,et ...

  9. uva 1331 - Minimax Triangulation(dp)

    option=com_onlinejudge&Itemid=8&page=show_problem&category=514&problem=4077&mosm ...

随机推荐

  1. ThinkPHP Http工具类(用于远程采集 远程下载) phpSimpleHtmlDom采集类库_Jquery筛选方式 使用phpQuery轻松采集网页内容http://www.thinkphp.cn/extend/541.html

    [php]代码库 view sourceprint? <?php // +------------------------------------------------------------ ...

  2. Django缓存,信号,序列化

    缓存 1.缓存的简介 在动态网站中,用户所有的请求,服务器都会去数据库中进行相应的增,删,查,改,渲染模板,执行业务逻辑,最后生成用户看到的页面. 当一个网站的用户访问量很大的时候,每一次的的后台操作 ...

  3. 4_python之路之模拟工资管理系统

    python之路之模拟工资管理系统 1.程序说明:Readme.txt 1.程序文件:salary_management.py info.txt 2.程序文件说明:salary_management. ...

  4. Linux 上通过binlog文件 恢复mysql 数据库详细步骤

    一.binlog 介绍 服务器的二进制日志记录着该数据库的所有增删改的操作日志(前提是要在自己的服务器上开启binlog),还包括了这些操作的执行时间.为了显示这些二进制内容,我们可以使用mysqlb ...

  5. Julia - 短路求值

    && 和 || 的布尔运算符被称为短路求值 它们连接一系列布尔表达式,仅计算最少的表达式来确定整个链的布尔值 在表达式 a && b 中,只有 a 为 true 时才计 ...

  6. Disconf实践指南:改造篇

    上一篇文章Disconf实践指南:使用篇介绍了如何在项目中应用disconf,虽然实现了分布式配置的实时刷新,但是我们希望能够去除所有的配置文件,把配置都交给disconf管理,本地只需要实现配置监听 ...

  7. Python图片转字符

    前段时间学习pillow写的,可以通过改变font_map改变转换的深度和字符.思路是先转换黑白大小,读取黑白值取范围读font_map转变. from PIL import Image,ImageD ...

  8. oracle查看登录到oracle服务器的客户端ip

    1. 在sys模式下创建一个表,用于记录客户端登录数据库服务器的详细信息. 1 create table login_history 2 ( 3 username varchar2(60), --用户 ...

  9. qrcode——js生成二维码

    1.引入 qrcode.min.js(点击下载demo) 2.html: <div id="qrcode"></div> js: var qrcode = ...

  10. GetHashCode作用

    除了以下的转载,再补充几点: 1.相同对象的hashcode一定相同,不同的hashcode不一定不相同. 2.好的散列算法可以更均匀的分布,进而可以更快的索引 3.据说,值对象的hashcode由第 ...