嵌套矩形问题(初级)算法竞赛紫书

题目描述

有 n 个矩形,每个矩形可以用 a,b来描述,表示长和宽。矩形 X(a,b)可以嵌套在矩形 Y(c,d)中当且仅当 a <c,b<d或者 b<c,a<d

(相当于旋转 90 度)。例如(1,5)可以嵌套在(6,2)内,但不能嵌套在(3,4)中。你的任务是选出尽可能多的矩形排成一行,

使得除最后一个外,每一个矩形都可以嵌套在下一个矩形内。

输入

第一行是一个正正数 N(0<N<10),表示测试数据组数。

每组测试数据的第一行是一个正正数 n,表示该组测试数据中含有矩形的个数 (n≤1000)。

随后的 n 行,每行有两个数 a,b(0<a,b≤100),表示矩形的长和宽。

 

输出

每组测试数据都输出一个数,表示最多符合条件的矩形数目,每组输出占一行。

样例输入

1
10
1 2
2 4
5 8
6 10
7 9
3 1
5 8
12 10
9 7
2 2

样例输出

5

解题思路:d(i,G)这个函数,表示的是,从矩形i出发的最长路长度,递归最好是debug去走一走,不要太深究。

先用自己的脑袋想一想,如果是人为的去数嵌套的矩形,应该怎么数呢

找到一个矩形A,然后再找到比这个矩形还要大的矩形B,然后找到比B大的矩形C……依次这样找

那我们的最多矩形个数,是不是应该先找到最小的那个矩形,然后找下一个比他大一点的,依次。

得到的一个想法就是:转换成求最长路的问题!DFS!

import java.util.Scanner;

public class Main {

	/**
	 * @param args
	 */
	static int t[];
	static int n=0;
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner in=new Scanner(System.in);
		int N=in.nextInt();//N组数据
		while(N-->0){
		n=in.nextInt();//矩形的个数n
		int arr[][]=new int[n][2];
		for(int i=0;i<n;i++)
			for(int j=0;j<2;j++){
				arr[i][j]=in.nextInt();//把矩形的长和宽录入
			}
		
		int G[][]=new int[n][n];
		t=new int[n];
		for(int i=0;i<n;i++)
			for(int j=0;j<n;j++){
				if((arr[i][0]<arr[j][0]&&arr[i][1]<arr[j][1])||(arr[i][0]<arr[j][1]&&arr[i][1]<arr[j][0]))
					G[i][j]=1;//如果满足题目条件,就表示,i可以放在j矩形里面,表示i和j是连通的
			}
		
		int max=-1;
		for(int i=0;i<n;i++){//从第一个矩形开始遍历,然后走遍可以嵌套这个矩形的所有矩形
			if(d(i,G)>max){//取最大的路径
				max=d(i,G);
			}
		}
		
		System.out.println(max);}
	}

	private static int d(int i, int[][] G) {
		// TODO Auto-generated method stub
		int ans=t[i];
		if(ans>0)return ans;//如果我已经走过i的所有连通图,那么我就直接返回,防止多遍历的情况,记忆划!
		ans=1;//每个矩形初始路径都是1撒
		for(int j=0;j<n;j++){
			if(G[i][j]==1){//如果j矩形和i矩形是连通 的,就接着走
				ans=Math.max(ans, d(j, G)+1); //比较当前的路径和他所连通给的那个矩形的最长路径
				t[i]=ans;//记忆化,给路径赋值。
			}
		}
		return ans;
		
	}

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值