UVA437 The Tower of Babylon

题解

初始时给了 \(n\) 种长方体方块,每种有无限个,对于每一个方块,我们可以选择一面作为底。然后用这些方块尽可能高地堆叠成一个塔,要求只有一个方块的底的两条边严格小于另一个方块的底的两条边,这个方块才能堆在另一个上面

问题的思考在于每种方块有无限个,如果我们直接利用该条件问题会变得比较复杂。其实仔细考虑方块堆叠的要求,会发现这是一个约束很强的条件。

注意到,方块堆叠的要求描述的对象不只是方块本身,更细地说,它应该描述的是方块摆放方式。一个长方体方块有三个面可以作为底(另三个面为对面,面与面对应相同),选择其中一个面后又需要再分两种摆放方式。所以对每种方块应该有六种摆放方式。用向量可以描述这六种摆放方式。前两个数字表示底面的长和宽,第三个数字表示高。

  1. \((x_i, y_i, z_i)\)
  2. \((y_i, x_i, z_i)\)
  3. \((y_i, z_i, x_i)\)
  4. \((z_i, y_i, x_i)\)
  5. \((x_i, z_i, y_i)\)
  6. \((z_i, x_i, y_i)\)

根据方块堆叠的要求,我们可以进一步得出,每种方块摆放方式(共 \(6n\) 种)在堆叠过程中最多出现一次。否则,存在一种摆放方式至少出现了两次,对于该种方块摆放方式,无论谁在上谁在下,都会存在一个方块的底的两条边等于另一个方块的底的两条边的情况,与严格小于相悖。所以对于每种方块摆放方式,我们可以选择“摆放”或是“不摆放”。

我们进一步思考方块堆叠的要求,它要保证底的两条边都得严格小于另一底的两条边,因此我们可以先对其中一条边做一个排序,再保证“选出的所有方块”的另一条边堆叠时依次严格小于即可。也就是说可以将二维的问题通过预处理排序将为一维的问题,而且可以进一步发现该一维问题是比较典型的动态规划问题(最长上升子序列)。

对在 \(x\) 轴上的每条边做一个排序(从大到小),然后根据 \(y\) 轴上的边的值选择“摆放”或是“不摆放”,最后要使得 \(z\) 轴上的值加和最大。使用一维 \(dp\) 数组记录状态,\(dp[i]\) 表示以第 \(i\) 个已摆放的前 \(i\) 个方块摆放方式的最大高度。

状态转移方程

\(dp[i]\) 状态表示已经“摆放”了第 \(i\) 号方块摆放方式,达到最大高度的堆叠方式可能需要垫一个方块,也可能不需要。如果垫一个方块则该方块的摆放方式只能是前面 \(i-1\) 个方块摆放方式中的一个(预处理时已将方块摆放方式排序,后面的方块一定不满足要求),由此可得状态转移方程:

\[dp[i] = \max \left( \max_{0 \leqslant j \leqslant i - 1} dp(j), 0 \right) + blocks[i].g
\]

状态搜索方向

直接将 \(dp[i]\) 从左至右依次更新即可。

程序:

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. #include<iostream>
  5. #include<vector>
  6. using namespace std;
  7. int n, x, y, z, cnt = 0;
  8. struct node {
  9. int c, k, g;
  10. node(int x, int y, int z) {
  11. c = x; k = y; g = z;
  12. }
  13. };
  14. vector<node> blocks;
  15. int dp[305];
  16. bool cmp(node a, node b) {
  17. if (a.c > b.c) return true;
  18. else if (a.c == b.c) {
  19. if (a.g > b.g) return true;
  20. else return false;
  21. }
  22. else return false;
  23. }
  24. int main()
  25. {
  26. while (cin >> n && n != 0) {
  27. blocks.clear();
  28. for (int i = 0; i < n; ++i) {
  29. scanf("%d %d %d", &x, &y, &z);
  30. // 每个方块六种摆放方式
  31. blocks.push_back(node(x, y, z));
  32. blocks.push_back(node(y, x, z));
  33. blocks.push_back(node(x, z, y));
  34. blocks.push_back(node(z, x, y));
  35. blocks.push_back(node(z, y, x));
  36. blocks.push_back(node(y, z, x));
  37. }
  38. // 排序
  39. sort(blocks.begin(), blocks.end(), cmp);
  40. memset(dp, -1, sizeof(dp));
  41. int ans = -1;
  42. for (int i = 0; i < 6 * n; ++i) {
  43. dp[i] = blocks[i].g;
  44. for (int j = 0; j < i; ++j) {
  45. if (blocks[i].c < blocks[j].c && blocks[i].k < blocks[j].k)
  46. dp[i] = max(dp[j] + blocks[i].g, dp[i]);
  47. }
  48. ans = max(ans, dp[i]);
  49. }
  50. printf("Case %d: maximum height = %d\n", ++cnt, ans);
  51. }
  52. return 0;
  53. }

ACM - 动态规划 - UVA437 The Tower of Babylon的更多相关文章

  1. [动态规划]UVA437 - The Tower of Babylon

     The Tower of Babylon  Perhaps you have heard of the legend of the Tower of Babylon. Nowadays many d ...

  2. Uva437 The Tower of Babylon

    https://odzkskevi.qnssl.com/5e1fdf8cae5d11a8f572bae96d6095c0?v=1507521965 Perhaps you have heard of ...

  3. UVa437 The Tower of Babylon(巴比伦塔)

    题目 有n(n<=30)种立方体,每种有无穷多个,摞成尽量高的柱子,要求上面的立方体要严格小于下面的立方体. 原题链接 分析 顶面的大小会影响后续的决策,但不能直接用d[a][b]来表示,因为可 ...

  4. 【DP】【Uva437】UVA437 The Tower of Babylon

    传送门 Description Input Output Sample Input Sample Output Case : maximum height = Case : maximum heigh ...

  5. UVa 437 The Tower of Babylon(经典动态规划)

    传送门 Description Perhaps you have heard of the legend of the Tower of Babylon. Nowadays many details ...

  6. UVA437-The Tower of Babylon(动态规划基础)

    Problem UVA437-The Tower of Babylon Accept: 3648  Submit: 12532Time Limit: 3000 mSec Problem Descrip ...

  7. DAG 动态规划 巴比伦塔 B - The Tower of Babylon

    题目:The Tower of Babylon 这是一个DAG 模型,有两种常规解法 1.记忆化搜索, 写函数,去查找上一个符合的值,不断递归 2.递推法 方法一:记忆化搜索 #include < ...

  8. UVa 437 The Tower of Babylon

    Description   Perhaps you have heard of the legend of the Tower of Babylon. Nowadays many details of ...

  9. POJ 2241 The Tower of Babylon

    The Tower of Babylon Time Limit: 1000ms Memory Limit: 65536KB This problem will be judged on PKU. Or ...

随机推荐

  1. 【windows 访问控制】三、访问控制列表 ACL=DACL+SACL

    访问控制列表(ACL:Access Control List) ACL列表的结构 ACL 中的每个 ACE 标识一个受信者,并指定该受信者访问规则.安全对象的安全描述符 可以包含两种类型的 ACL:D ...

  2. 《Java编程思想》学习笔记(详细)

    目录 01 对象导论 02 一切都是对象 03 操作符 04 控制执行流程 05 初始化与清理 06 访问权限控制 07 复用类(继承) 08 多态 09 接口 10 内部类 11 持有对象 12 通 ...

  3. Mac Mini 安装Ubuntu20.04 KVM

    在一台 Mac Mini mid 2011上安装Ubuntu20.04并配置KVM环境, 过程也适用于其他版本的Mac Mini. 硬件配置 I5 2415, 内存8G*2, 硬盘 SSD 500G ...

  4. 洛谷P3267.侦察守卫

    题目大意 一颗 \(n(1\leq n\leq 5\times 10^5)\) 个节点的树,在某一点 \(i\) 花费 \(w_{i}(w_{i}\leq 1000)\) 放置一个侦察守卫后可以监视到 ...

  5. c语言刷 DFS题记录

    144. 二叉树的前序遍历 /** * Definition for a binary tree node. * struct TreeNode { * int val; * struct TreeN ...

  6. Linux CentOS7.X-文件操作命令

    一.文件新增,touch 1.touch fileName,其中fileName表示文件名称,代表创建一个空文件: 2.touch fn1 fn2 fn3....fnn,其中fn1至fnn表示n个不同 ...

  7. Scala语法2

    练习 package scala_01.practice import org.junit.{Before, Test} import scala.collection.immutable impor ...

  8. 矩池云 | 新冠肺炎防控:肺炎CT检测

    连日来,新型冠状病毒感染的肺炎疫情,牵动的不仅仅是全武汉.全湖北,更是全国人民的心,大家纷纷以自己独特的方式为武汉加油!我们相信坚持下去,终会春暖花开. 今天让我们以简单实用的神经网络模型,来检测肺炎 ...

  9. laravel7 百度智能云检测内容及图片

    1:百度智能云,获取AppID,API Key,Secret Key https://console.bce.baidu.com/ai/?_=1642339692640&exraInfo=ai ...

  10. (七)React Ant Design Pro + .Net5 WebApi:后端环境搭建-日志、异常处理

    一.日志 日志具有帮助开发者快速的定位问题,记录各种信息,配合其他分析框架使用等等功能,收集日志的各类框架如:Log4net.NLog.Exceptionless.Serilog等等,百度或园子里介绍 ...