LIS的简单应用:UVA-437
上一次紫芝详细地介绍了动态规划中的经典问题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的更多相关文章
- UVA 437 十九 The Tower of Babylon
The Tower of Babylon Time Limit:3000MS Memory Limit:0KB 64bit IO Format:%lld & %llu Subm ...
- UVA 437 巴比伦塔 【DAG上DP/LIS变形】
[链接]:https://cn.vjudge.net/problem/UVA-437 [题意]:给你n个立方体,让你以长宽为底,一个个搭起来(下面的立方体的长和宽必须大于上面的长和宽)求能得到的最长高 ...
- UVa 437 (变形的LIS) The Tower of Babylon
题意: 有n种类型的长方体,每种长方体的个数都有无限个.当一个长方体的长和宽分别严格小于另一个长方体的长和宽的时候,才可以把这个放到第二个上面去.输出这n种长方体能组成的最大长度. 分析: 虽说每种都 ...
- uva 437,巴比伦塔
题目链接:https://uva.onlinejudge.org/external/4/437.pdf 题意:巴比伦塔: 给出n种立方体,一个立方体能放到另一个立方体上,必须满足,底面一定要小于下面的 ...
- UVA - 437 The Tower of Babylon(dp-最长递增子序列)
每一个长方形都有六种放置形态,其实可以是三种,但是判断有点麻烦直接用六种了,然后按照底面积给这些形态排序,排序后就完全变成了LIS的问题.代码如下: #include<iostream> ...
- UVA 437 The Tower of Babylon(DAG上的动态规划)
题目大意是根据所给的有无限多个的n种立方体,求其所堆砌成的塔最大高度. 方法1,建图求解,可以把问题转化成求DAG上的最长路问题 #include <cstdio> #include &l ...
- 【UVA 437】The Tower of Babylon(记忆化搜索写法)
[题目链接]:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_probl ...
- UVa 437 The Tower of Babylon(经典动态规划)
传送门 Description Perhaps you have heard of the legend of the Tower of Babylon. Nowadays many details ...
- UVa 437 The Tower of Babylon
Description Perhaps you have heard of the legend of the Tower of Babylon. Nowadays many details of ...
随机推荐
- MFC窗口消息PostMessage和SendMessage
以前这些消息用得比较少,但是今天碰到了个事儿,我看非用消息不可. 事情是这样的,我在线程中需要刷新对话框上面的内容,但是每每执行到UpdateData时就出现了断言错误. 查了相关资料,发现这个可能是 ...
- Codeforces Round #374 (Div. 2) B. Passwords —— 基础题
题目链接:http://codeforces.com/contest/721/problem/B B. Passwords time limit per test 2 seconds memory l ...
- 10个常见的 Android 新手误区
在过去十年的移动开发平台中,作为资深的移动开发人员,我们认为Android平台是一个新手最广为人知的平台.它不仅是一个廉价的工具,而且有着良好的开发社区,以及从所周知的编程语言(Java),使得开发A ...
- windows 下python搭建环境
一.python安装 1,首先访问https://www.python.org/downloads/windows/去下载python版本. 2. 选择3.5版本,installer文件类型(因为3. ...
- SpringMVC 注释@PathVariable
@PathVariable 是用来获得请求url中的动态参数的: @ResponseBody @RequestMapping(value="/pointUpload/{userid}&quo ...
- python中元组tuple
python中列表(list)和元组(tuple)有很多相似的地方,它们都是容器,由一系列的对象构成,都可以包含任意类型的元素,甚至是一个序列. list和tuple的不同首先体现在写法上: li ...
- I.MX6 Surfaceflinger 机制
/**************************************************************************** * I.MX6 Surfaceflinger ...
- CodeForces768B:Code For 1 (分治)
Jon fought bravely to rescue the wildlings who were attacked by the white-walkers at Hardhome. On hi ...
- BZOJ_2002_[Hnoi2010]Bounce 弹飞绵羊_LCT
BZOJ_2002_[Hnoi2010]Bounce 弹飞绵羊_LCT Description 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏. ...
- IntelliJ IDEA 2018 设置代码提示对大小写不敏感
setting->Editor->General->Code Completion取消勾选Match case