嵌套矩形
描述:
有n 个矩形,每个矩形可以用a; b 来描述,表示长和宽。矩形X(a; b) 可以嵌套在矩形Y (c; d)
中当且仅当a < c; b < d 或者b < c; a < d(相当于旋转X90 度)。例如(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
分析
与Floyd求最短路径思想基本一致,本题实质上是求DAG 中不固定起点的最长路径。
设d[i] 表示从结点i 出发的最长长度,状态转移方程如下:
dp[i]=max{dp[j]+1,(i,j)∈E}
三重循环的遍历DP。。
其中,E 为边的集合。最终答案是d[i] 中的最大值。
若要求路径,则可用下面的代码
public static void print(int i,int[]d,boolean[][]graph){
System.out.print(i+" ");
for(int j=0;j<d.length;j++){
if(d[i]==d[j]+1&&graph[i][j]){
print(j,d,graph);
return;
}
}
System.out.println();
}
附上Java代码:
import java.util.Scanner;
/**
*
* @author Administrator
*/
public class MyJava {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int num = scan.nextInt();
boolean[][] graph = new boolean[num][num];
int[] dp = new int[num];
Point[] po = new Point[num];
for (int i = 0; i < num; i++) {
int x = scan.nextInt();
int y = scan.nextInt();
po[i] = new Point(x, y);
}
for (int i = 0; i < num; i++) {
dp[i] = 1;
for (int j = 0; j < num; j++) {
if (po[i].x > po[j].x && po[i].y > po[j].y || po[i].x > po[j].y && po[i].y > po[j].x) { //代表存在i->j路径
graph[i][j] = true;
}
}
}
for (int k = 0; k < num; k++) { //k置外循环
for (int i = 0; i < num; i++) {
for (int j = 0; j < num; j++) {
if (graph[i][j]) {
dp[i] = Math.max(dp[i], dp[j] + 1);
}
}
}
}
int max = 0,maxi=0;
for (int i = 0; i < num; i++) {
if (max < dp[i]) {
max = dp[i];
maxi=i;
}
}
System.out.println("最长嵌套矩形个数为:" + max);
print(maxi,dp,graph);
}
static class Point {
int x, y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
}
public static void print(int i,int[]d,boolean[][]graph){
System.out.print(i+" ");
for(int j=0;j<d.length;j++){
if(d[i]==d[j]+1&&graph[i][j]){
print(j,d,graph);
return;
}
}
System.out.println();
}
}