有 nn 个矩形,每个矩形可以用 a,ba,b 来描述,表示长和宽。矩形 X(a,b)X(a,b) 可以嵌套在矩形 Y(c,d)Y(c,d) 中当且仅当 a <c,b<da<c,b<d 或者 b<c,a<db<c,a<d(相当于旋转 9090 度)。例如(1,51,5)可以嵌套在(6,26,2)内,但不能嵌套在(3,43,4)中。你的任务是选出尽可能多的矩形排成一行,使得除最后一个外,每一个矩形都可以嵌套在下一个矩形内。
输入格式
第一行是一个正正数 N(0<N<10)N(0<N<10),表示测试数据组数。
每组测试数据的第一行是一个正正数 nn,表示该组测试数据中含有矩形的个数 (n \le 1000)(n≤1000)。
随后的 nn 行,每行有两个数 a,b(0<a,b \le 100)a,b(0<a,b≤100),表示矩形的长和宽。
输出格式
每组测试数据都输出一个数,表示最多符合条件的矩形数目,每组输出占一行。
输出时每行末尾的多余空格,不影响答案正确性
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int M[1000][1000],d[1000],n,maxn;//d数组存放从i开始最长序列
struct edge{
int x,y;
bool operator < (const edge& rhs)const{
return this -> x < rhs.x;
}
};
edge e[1000];
int dp(int i){//记忆化搜索
int& ans = d[i];//方法二 实用引用修改数组 方法一 利用赋值语句返回值
if(ans){
return ans;
}
ans = 1;
for(int j = 0;j < n; ++j){
if(M[i][j]){
ans = max(ans,dp(j) + 1);
}
}
return ans;
}
//void print(int i){
// printf("%d %d %d\n",i,e[i].x,e[i].y);
// for(int j = 0;j < n; ++j){
// if(M[i][j] && d[i] == d[j] + 1){
// print(j);
// break;
// }
// }
//}
int main(){
int T,i,j,mi;
cin >> T;
while(T--){
maxn = 0;
memset(M,0,sizeof(M));
memset(d,0,sizeof(d));
scanf("%d",&n);
for(i = 0;i < n; ++i){
scanf("%d%d",&e[i].x,&e[i].y);
if(e[i].x > e[i].y){
int tmp = e[i].x;
e[i].x = e[i].y;
e[i].y = tmp;
}
}
sort(e,e + n);
for(i = 0;i < n - 1; ++i){
for(j = i + 1;j < n; ++j){
if(e[i].y < e[j].y && e[i].x < e[j].x)
M[i][j] = 1;
}
}
/*for(i = n - 2;i >= 0; --i){//递推法
for(j = i + 1;j < n; ++j){
if(e[i].y < e[j].y && e[i].x < e[j].x)
//M[i][j] = 1;
d[i] = max(d[i],d[j] + 1);
if(d[i] > maxn)
maxn = d[i];
}
}*/
for(i = 0;i < n; ++i){
int t = dp(i);
if(t > maxn){
maxn = t;
mi = i;
}
}
printf("%d\n",maxn);
//print(mi);
}
return 0;
}
矩形嵌套也是一个二元关系,使用邻接矩阵存储图。
状态转移方程d[i] = max(d[i], d[j] + 1)。