上一次紫芝详细地介绍了动态规划中的经典问题LIS,今天我们抽出一个类似思想的简单题目进行实践练习。

The Tower of Babylon(巴比伦塔)

Perhaps you have heard of the legend of the Tower of Babylon. Nowadays many details of this tale have been forgotten. So now, in line with the educational nature of this contest, we will tell you the whole story:

你可能对巴比伦的传说有所耳闻,但如今诸多细节早已随风而逝。现在为了与比赛的教育目的相一致,我们将还原整个故事:

The babylonians had n types of blocks, and an unlimited supply of blocks of each type. Each type-i block was a rectangular solid with linear dimensions (xi,yi,zi). A block could be reoriented so that any two of its three dimensions determined the dimensions of the base and the other dimension was the height.

巴比伦人有 n 种无限供给的砖块,每个砖块 i 是三边为 xi,yi,zi 的长方体,可以以任意两边构成底,第三边为高。

They wanted to construct the tallest tower possible by stacking blocks. The problem was that, in building a tower, one block could only be placed on top of another block as long as the two base dimensions of the upper block were both strictly smaller than the corresponding base dimensions of the lower block. This meant, for example, that blocks oriented to have equal-sized bases couldn’t be stacked.

欲砌砖以筑最高楼。以上一个砖的两底边均严格小于下一个砖的两底边为原则(相等不算数)。

Your job is to write a program that determines the height of the tallest tower the babylonians can build with a given set of blocks.

作为程序员的你来写个bug看看用他给的砖能堆多高。

Input

The input file will contain one or more test cases. The first line of each test case contains an integer n, representing the number of different blocks in the following data set. The maximum value for n is 30. Each of the next n lines contains three integers representing the values xi, yi and zi. Input is terminated by a value of zero (0) for n.

输入:多组数据。每组第一行给出种类数 n,最大30;接下来 n 行每行给出这种砖的长宽高。输入以n==0结束。

Output

For each test case, print one line containing the case number (they are numbered sequentially starting from 1) and the height of the tallest possible tower in the format ‘Case case: maximum height = height’

输出:对于每组数据输出最高塔的高度值,格式Case要求见样例。

Sample Input

1

10 20 30

2

6 8 10

5 5 5

7

1 1 1

2 2 2

3 3 3

4 4 4

5 5 5

6 6 6

7 7 7

5

31 41 59

26 53 58

97 93 23

84 62 64

33 83 27

0

Sample Output

Case 1: maximum height = 40

Case 2: maximum height = 21

Case 3: maximum height = 28

Case 4: maximum height = 342

首先建议自己思考、编程实现并提交~

其实跟LIS还是不完全一样的(废话),但个人觉得思想都是对于每个元素都查一遍他前头有几个符合条件的

简单再现一下我个人的思考过程:

啊这是单减序列啊 ----> 如果就按他输入的顺序扫一遍,遇到“大小中”这样的顺序我这个“中”好像插不进去啊 ----> 那先排个序? ----> 怎么排啊?俩边?面积? ----> 诶按面积排会不会出乱子呢?最后要严格递减的,那排后面的双边都小,肯定比前面的面积小啊;不在这个序列里的人他站哪都无所谓吧…… ----> 开始编程

放出蒟蒻代码:

 #include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std; struct block
{
int a;
int b;
int height;
block(int x, int y, int z){a = x; b = y; height = z;}
}; struct cmp
{
bool operator() (const block& x, const block& y)
{
return x.a * x.b > y.a * y.b;
}
}; bool yes(block x, block y)
{
return (x.a > y.a && x.b > y.b) || (x.a > y.b && x.b > y.a);
} int main()
{
int n, kase = ;
while (~scanf("%d", &n) && n)
{
vector <block> v;
for (int i = ; i < n; i++)
{
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
//每块都有三种用法
v.push_back(block(a,b,c));
v.push_back(block(a,c,b));
v.push_back(block(b,c,a));
} sort(v.begin(), v.end(), cmp()); int ans = v[].height;
int dp[] = {};
for (int i = ; i < v.size(); i++)
{
dp[i] = v[i].height;//这是不能省的一步
//万一前面没有一个可以匹配的,它本身高度就是本序列的一血
for (int j = ; j < i; j++)//前面扫荡一遍
if (yes(v[j], v[i]))//双边严格小于
dp[i] = max(dp[i], dp[j] + v[i].height);
ans = max(ans, dp[i]);
} printf("Case %d: maximum height = %d\n", ++kase, ans);
}
}

刘汝佳大爷给的教程是用记忆化搜索做的,将此题归类为DAG上的最长路问题。我稍加注释,下面贴上代码大家一起观摩~

 // UVa437 The Tower of Babylon

 // Rujia Liu

 // 算法:DAG上的最长路,状态为(idx, k),即当前顶面为立方体idx,其中第k条边(排序后)为高

 #include<cstdio>

 #include<cstring>

 #include<algorithm>

 using namespace std;

 #define REP(i,n) for(int i = 0; i < (n); i++)
//此处把for循环宏定义了一下,下面就比较好写 const int maxn = + ; int n, blocks[maxn][], d[maxn][]; void get_dimensions(int* v, int b, int dim) { int idx = ; REP(i,) if(i != dim) v[idx++] = blocks[b][i];
} int dp(int i, int j) { int& ans = d[i][j];
//加了&以后下面对ans的读写修改就相当于对d[i][j]的修改 if(ans > ) return ans; ans = ; int v[], v2[]; get_dimensions(v, i, j);
//这个j的用途就是决定一下哪个边作为高 REP(a,n) REP(b,) { get_dimensions(v2, a, b); if(v2[] < v[] && v2[] < v[]) ans = max(ans, dp(a,b));
//因为他的边存的时候就是排好序的,故不会纠结旋转90°会不会成立的问题 } ans += blocks[i][j]; return ans; } int main() { int kase = ; while(scanf("%d", &n) == && n) { REP(i,n) { REP(j,) scanf("%d", &blocks[i][j]); sort(blocks[i], blocks[i]+);
//将三边由小到大排序
} memset(d, , sizeof(d));
//这个d就是个dp数组,d[i][j]表示:
//i种类的砖以第j条边做高,且这块砖作为塔顶时,能达到的最大高度 int ans = ; REP(i,n) REP(j,) ans = max(ans, dp(i,j));//这里是个二重循环 printf("Case %d: maximum height = %d\n", ++kase, ans); } return ;
}

LIS的简单应用:UVA-437的更多相关文章

  1. UVA 437 十九 The Tower of Babylon

    The Tower of Babylon Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Subm ...

  2. UVA 437 巴比伦塔 【DAG上DP/LIS变形】

    [链接]:https://cn.vjudge.net/problem/UVA-437 [题意]:给你n个立方体,让你以长宽为底,一个个搭起来(下面的立方体的长和宽必须大于上面的长和宽)求能得到的最长高 ...

  3. UVa 437 (变形的LIS) The Tower of Babylon

    题意: 有n种类型的长方体,每种长方体的个数都有无限个.当一个长方体的长和宽分别严格小于另一个长方体的长和宽的时候,才可以把这个放到第二个上面去.输出这n种长方体能组成的最大长度. 分析: 虽说每种都 ...

  4. uva 437,巴比伦塔

    题目链接:https://uva.onlinejudge.org/external/4/437.pdf 题意:巴比伦塔: 给出n种立方体,一个立方体能放到另一个立方体上,必须满足,底面一定要小于下面的 ...

  5. UVA - 437 The Tower of Babylon(dp-最长递增子序列)

    每一个长方形都有六种放置形态,其实可以是三种,但是判断有点麻烦直接用六种了,然后按照底面积给这些形态排序,排序后就完全变成了LIS的问题.代码如下: #include<iostream> ...

  6. UVA 437 The Tower of Babylon(DAG上的动态规划)

    题目大意是根据所给的有无限多个的n种立方体,求其所堆砌成的塔最大高度. 方法1,建图求解,可以把问题转化成求DAG上的最长路问题 #include <cstdio> #include &l ...

  7. 【UVA 437】The Tower of Babylon(记忆化搜索写法)

    [题目链接]:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_probl ...

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

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

  9. UVa 437 The Tower of Babylon

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

随机推荐

  1. html5--select与HTML5新增的datalist元素

    html5--select与HTML5新增的datalist元素 学习要点 掌握select元素与datalist元素的使用 select元素 用来建立一个下拉菜单选项列表 不仅可以在表单中使用,还可 ...

  2. UUID 和 GUID 的区别(转)

    UUID是一个由4个连字号(-)将32个字节长的字符串分隔后生成的字符串,总共36个字节长.比如:550e8400-e29b-41d4-a716-446655440000 http://gohands ...

  3. 简单数位DP

    https://cn.vjudge.net/problem/HDU-4722 懒得写看,代码注释吧;主要存板子 #include <cstdio> #include <cstring ...

  4. 条件变量pthread_cond_wait()和pthread_cond_signal()详解

    条件变量        条件变量是利用线程间共享的全局变量进行同步的一种机制,主要包括两个动作:一个线程等待"条件变量的条件成立"而挂起:另一个线程使"条件成立" ...

  5. bzoj 3309 DZY Loves Math——反演+线性筛

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3309 像这种数据范围,一般是线性预处理,每个询问 sqrt (数论分块)做. 先反演一番.然 ...

  6. PYTHON 异常处理 二 TRY 模块

    异常处理 捕捉异常可以使用try/except语句. try/except语句用来检测try语句块中的错误,从而让except语句捕获异常信息并处理. 如果你不想在异常发生时结束你的程序,只需在try ...

  7. pytest用例setup和teardown

    函数式以下两种: setup_function/teardown_function  每个用例开始和结束调用一次 setup_module/teardown_module     setup_modu ...

  8. HDU 1394 树状数组+离散化求逆序数

    对于求逆序数问题,学会去利用树状数组进行转换求解方式,是很必要的. 一般来说我们求解逆序数,是在给定一串序列里,用循环的方式找到每一个数之前有多少个比它大的数,算法的时间复杂度为o(n2). 那么我们 ...

  9. docker 学习(六) export/import/load/save images

    export/import 是一对命令:   load/save是一对命令 一: export / import使用 1:  查看镜像:  docker ps -a 2:导出镜像:docker  ex ...

  10. 计时器 vb

    十分钟 我们寒假就是这么长!! vb 执行cmd   :              shell "cmd /c DOS命令" vb 取系统日期: Print Date; " ...