计蒜客#T1408矩形嵌套

有 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)。

发布了53 篇原创文章 · 获赞 0 · 访问量 717

猜你喜欢

转载自blog.csdn.net/weixin_38894974/article/details/104631405