- 问题描述
-
有n个长方体,每个长方体可以用a,b,c来描述,表示长和宽。长方体(a,b,c)(a<=b<=c)可以嵌套在长方体(x,y,z)(x<=y<=z)内当且仅当a<x,b<y,c<z。例如(1,5,6)可以嵌套在(2,7,8)内,但不能嵌套在(1,2,30)内。你的任务是选出尽可能多的长方体排成一行,使得除最后一个外,每个长方体都可以嵌套在下一个长方体内。
- 输入
-
每组测试数据的第一行是一个正整数n,表示该组测试数据中含有长方体的个数(n<=1000)。
随后的n行,每行有三个数a,b,c(0<a,b,c<100),表示长方体的长和宽和高。
- 输出
-
每组测试数据都输出一个数,表示最多符合条件的长方体数目,每组输出占一行。
- 样例输入
-
4 1 1 1 1 2 1 2 2 2 3 5 4
- 样例输出
-
3
类型:DAG上的最长路,排序DP
思路:
1、把每一个长方体抽象成一个个的节点
2、如果一个长方体可以覆盖另一个长方体,那么就在这两个长方体代表的节点上连一条有向边
3、寻找到从某个节点出发可以得到的最长路
接下来就有一个问题:
那么如何记录下从某个节点出发可以得到的最长路呢?
设dp[i]表示从节点i出发可以得到的最长路,第一步只能走到它的相邻点,则有
dp[i] = max(dp[j]+1) (i,j)属于边集
代码如下:
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn=1000+5;
struct REC
{
int l,r,h;
}a[maxn];
int dp[maxn];//dp[i]表示从i开始能覆盖最多的长方体;
inline int cmp(REC A,REC B)
{
return A.l<B.l;
}
int main()
{
int N,n,i,j,p,q,r;
while(~scanf("%d",&n))
{
int aa[3];
for(i=0;i<n;i++)
{
scanf("%d%d%d",&aa[0],&aa[1],&aa[2]);
sort(aa,aa+3);
a[i].l=aa[0];
a[i].r=aa[1];
a[i].h=aa[2];
dp[i]=1;
}
sort(a,a+n,cmp);
int maxm=1;
for(i=1;i<n;i++)
{
for(j=i-1;j>=0;j--)
{
if(a[i].l>a[j].l&&a[i].r>a[j].r && a[i].h >a[j].h&&dp[i]<dp[j]+1)
dp[i]=dp[j]+1;
}
maxm=max(maxm,dp[i]);
}
printf("%d\n",maxm);
}
return 0;
}