台州 OJ 1322 Monkey and Banana 最长上升子序列

描述

一组研究人员正在设计一个测试猴子智商的实验。他们会在建筑物的屋顶上挂一根香蕉,同时给猴子一些块。如果猴子够聪明,就可以通过在顶部放一个块来建立一个塔,爬上去获得最喜欢的食物,到达香蕉。

研究人员有n种类型的块,并且每种类型的块都是无限制的。每个i型块是具有线性尺寸(xi,yi,zi)的矩形固体。块可以重新定向,使得其三维中的任何两个尺寸确定基部的尺寸,而另一个尺寸确定为高度。

他们想确保最高的塔可能通过堆叠块可以到达屋顶。问题在于,在建造塔楼时,一个块只能放置在另一块的顶部,只要上块的两个基本尺寸都严格小于下块的相应基座尺寸,因为必须有一些空间可供猴子踩踏。这意味着,例如,面向具有相等大小的基座的块不能被堆叠。

你的工作是编写一个程序,用来确定猴子可以用一组给定的块建立的最高塔的高度。

输入

输入文件将包含一个或多个测试用例。每个测试用例的第一行包含一个整数n,
表示以下数据集中不同块的数量。n的最大值为30. 
接下来的n行中的每一行包含表示值xi,yi和zi的三个整数。
n的值为零(0)终止输入。

输出

对于每个测试用例,打印一行包含案例编号(它们从1开始按顺序编号)和最高可能的塔的高度,格式为“Case case:maximum height = height”。

 
 
类似于最长上升子序列问题,不过有几个要注意的点。
1. 一个长方体最多可以有3个不同的底面,所以一个块最多可以用三次。
2. 最长上升子序列要求下标是递增的,但在这里,高度最高的塔使用的块的下标在数组中并不一定是递增的,在 dp 之前使用排序可以解决这个问题(具体写在代码注释里了)。 (╮(╯▽╰)╭ 这里愣了好久,真是越来越笨了)
 
代码:
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

const int MAX = 3*35;

struct Node{
    int x, y, z;
};

int n;
int dp[MAX];
Node node[MAX];

bool cmp(Node a, Node b){
    return a.x * a.y > b.x * b.y; 
}

int main(){
    //freopen("input.txt", "r", stdin);
    int T = 0;
    while(cin >> n && n != 0){
        for(int i=1; i<=3*n; i++){
            cin >> node[i].x >> node[i].y >> node[i].z;
            node[i+1].x = node[i].y;    //将块旋转, 一共可获得三种块 
            node[i+1].y = node[i].z;
            node[i+1].z = node[i].x;
            node[i+2].x = node[i].x;
            node[i+2].y = node[i].z;
            node[i+2].z = node[i].y;
            i += 2; 
        }
        
        //按照面积从大到小排序,则前面的一定不可能放在后面的块上,
        //即当前块为顶的塔的最大高度与后面的块无关。
        sort(node + 1, node + 1 + 3*n, cmp);
        dp[0] = 0;
        int maxH = 0;
        for(int i=1; i<=3*n; i++){
            dp[i] = node[i].z;
            for(int j=1; j<i; j++){
                if(node[i].x < node[j].x && node[i].y < node[j].y
                ||    node[i].x < node[j].y && node[i].y < node[j].x){
                    dp[i] = max(dp[i], dp[j] + node[i].z);
                }
            }
            maxH = max(maxH, dp[i]);
        }
        
        cout << "Case " << ++T << ": maximum height = " << maxH << endl; 
    }
}
原文地址:https://www.cnblogs.com/lighter-blog/p/7233758.html