上一次紫芝详细地介绍了动态规划中的经典问题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. 深入浅出剖析C语言函数指针与回调函数(一)【转】

    本文转载自:http://blog.csdn.net/morixinguan/article/details/65494239 关于静态库和动态库的使用和制作方法. http://blog.csdn. ...

  2. HDU2586 How far away? —— 倍增LCA

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586 How far away ? Time Limit: 2000/1000 MS (Java/Ot ...

  3. Codeforces Round #379 (Div. 2) E. Anton and Tree —— 缩点 + 树上最长路

    题目链接:http://codeforces.com/contest/734/problem/E E. Anton and Tree time limit per test 3 seconds mem ...

  4. Python作业之用户管理

    作业 流程图没有画,懒,不想画 readme没有写,懒,不想写.看注释吧233333 #! /usr/bin/env python # -*- coding: utf-8 -*- # __author ...

  5. codeforces 701C C. They Are Everywhere(尺取法)

    题目链接: C. They Are Everywhere time limit per test 2 seconds   memory limit per test 256 megabytes inp ...

  6. 内存泄漏分析工具tMemMonitor (TMM)使用简介

    C/C++由于灵活.高效的优点一直以来都是主流的程序设计语言之一,但是其内存的分配与释放均由程序员自己管理,当由于疏忽或错误造成程序未能释放不再使用的内存时就会造成内存泄漏.在大型.复杂的应用程序中, ...

  7. bzoj2962

    线段树+卷积 这个东西直接算不太好,但是合并两段结果却很方便,假设c[i]表示选i个数乘积的和,那么$a[i]=\sum_{j=0}^{i}{b[j]*c[i-j]}$ 线段树维护即可 #includ ...

  8. [转]windows10 1703 鼠标右键打开命令提示符cmd

    https://answers.microsoft.com/zh-hans/windows/forum/windows_10-performance/windows10-1703/8bdfdfea-4 ...

  9. css3单位em,rem,px,vw,vh等

    昨天发现了个好用的方法去设置手机端的rem单位,在这里记录下. html{ font-size:calc(100vw/7.5);} 这是按照750的设计稿(也就是iphone6的设计稿). 100vw ...

  10. Python死锁与递归锁

    Lock() 互斥锁会导致死锁,用RLock()递归锁代替. 递归锁:可以连续acquire多次,每acquire一次计数器+1(无论acquire的是哪个锁),只有计数为0才能被acquire mu ...