一组研究人员正在设计一项实验,以测试猴子的智商。
他们将挂香蕉在建筑物的屋顶,同时,提供一些砖块给这些猴子。
如果猴子足够聪明,它应当能够通过合理的放置一些砖块建立一个塔,并爬上去吃他们最喜欢的香蕉。
研究人员有n种类型的砖块,每种类型的砖块都有无限个。
第i块砖块的长宽高分别用xi,yi,zi来表示。
同时,由于砖块是可以旋转的.
在构建塔时,当且仅当A砖块的长和宽都分别小于B砖块的长和宽时,
A砖块才能放到B砖块的上面,因为必须留有一些空间让猴子来踩。
你的任务是编写一个程序,计算猴子们最高可以堆出的砖块们的高度。
题解
[线性DP--LIS模型]
分析:
通过题意,可以分析得出,每一种类型的砖可以分成 6 种不同类型的
在将其按照长宽小的放前面, 求LIS
(为什么要排序,因为LIS与序顺序有关)
(所以要构造一个序列使得 LIS尽可能长)
Code
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
#define read(a) scanf("%d", &a)
#define readl(a) scanf("%lld", &a)
#define readf(a) scanf("%lf", &a)
#define readc(a) scanf("%c", &a)
#define reads(a) scanf("%s", a)
#define Buff ios::sync_with_stdio(false)
#define mem(a) memset(a, 0, sizeof a)
#define pb push_back
const int INF = 1e9 + 7;
const int N = 1e5 + 7;
const int M = 1e6 + 7;
const ll mod = 1e9 + 7;
struct node
{
int x, y, z;
node(int x = 0, int y = 0, int z = 0):x(x), y(y), z(z){}
bool operator<(const node& A)const
{
return (x < A.x || (x == A.x && y < A.y));
}
}block[N];
int dp[N];
int main()
{
Buff;
int n, Case = 0;
while(cin >> n, n)
{
n *= 6;
for(int i = 1,xi,yi,zi; i <= n;)
{
cin >> xi >> yi >> zi;
block[i++] = node(xi, yi, zi);
block[i++] = node(xi, zi, yi);
block[i++] = node(yi, xi, zi);
block[i++] = node(yi, zi, xi);
block[i++] = node(zi, xi, yi);
block[i++] = node(zi, yi, xi);
}
sort(block+1, block+n+1);
int ans = 0;
for(int i = 1; i <= n; i++)
{
dp[i] = block[i].z;
for(int j = 1; j < i; j++)
if(block[j].x < block[i].x && block[j].y<block[i].y && dp[i] < dp[j] + block[i].z)
dp[i] = dp[j] + block[i].z;
ans = max(ans, dp[i]);
}
cout << "Case " << ++Case << ": maximum height = " << ans << "\n";
}
return 0;
}