上一次紫芝详细地介绍了动态规划中的经典问题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. ALSA lib调用实例

    1. Display Some PCM Types and Formats 2. Opening PCM Device and Setting Parameters /* This example o ...

  2. Chrome 插件 Vimium——让你脱离鼠标

    下面是帮助,按?就能出现.什么时候忘了可以随时查看.^_^

  3. 查询oracle数据库中的for update 中锁住的table表sql语句

    SELECT object_name, machine, s.sid, s.serial# FROM gv$locked_object l, dba_objects o, gv$session s W ...

  4. 实用jQuery代码片段

    maco精选的一些jQuery代码,也许你从中可以举一反三[代码] [JavaScript]代码001<p>002    <h3><span >★ 使用jQuery ...

  5. tensorflow实现图像的翻转

    from:https://blog.csdn.net/uestc_c2_403/article/details/72703097 tensorflow内部含有实现图像翻转的函数为 tf.image.f ...

  6. Apktool 和 Jeb 给出的不同的smali语法

    今天发现用Apktool和Jeb反编译出来的smali在语法上有一定区别,比如一个Java函数: private void packageNameCheck() { com.example.testf ...

  7. python os.system重定向stdout到变量 ,同时获取返回值

    Python执行系统命令的方法 os.system(),os.popen(),commands 最近在做那个测试框架的时候发现 Python 的另一个获得系统执行命令的返回值和输出的类. 最开始的时候 ...

  8. Request.UrlReferrer 实现页面刷新

    在使用Ajax 异步提交表单的时候,需要返回某些状态信息.但如果把需要返回的如分页.过滤的参数写在控制器的参数里面,会比较繁琐. 因此,1.可以在控制器里面使用 Request 对象的请求的URL. ...

  9. CF-798A

    A. Mike and palindrome time limit per test 2 seconds memory limit per test 256 megabytes input stand ...

  10. Httpclient入门代码

    /** * Project Name:httpClient * File Name:Test.java * Package Name:httpClient * Date:2017年11月9日上午8:3 ...