矩形嵌套
- 描述
- 有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
矩形嵌套問題。
因爲一個矩形無法直接或間接的嵌套在自己內部。所以叫有向無環圖。
任務是求有向無環圖的最長路徑,可以用d(i)來表示從結點i出發的最長路長度,第一步只能走到它的相鄰點假設爲 j,
因此 d(i) = max{d(j) + 1 (i, j) ∈ E (邊集)}
這樣的話,我們可以嘗試用記憶化搜索的方式來計算上式。
但是我們應該先把圖建立出來,用鄰接矩陣來表示,然後就記憶化搜索。
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<math.h>
#define MAXN 1010
using namespace std;
int x[MAXN], y[MAXN], G[MAXN][MAXN],d[MAXN];
int n;
int dp(int i)
{
int& ans = d[i]; // ans 是一個引用,對ans操作就是對d[i]操作
if(ans > 0) return ans; // 如果已經搜索過直接返回,減少搜索次數。
ans = 1; //如果沒有搜索,最小值爲1 即就它自己可以嵌套。
for(int j = 0; j < n; j++)
{
if(G[i][j])
ans = max(ans, dp(j) + 1);//判斷動歸方程,記憶化搜索
}
return ans;
}
int main()
{
int t, ans, i, j;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(i = 0; i < n; i++)
{
scanf("%d%d",&x[i],&y[i]);
if(x[i] > y[i])
{
int k;
k = y[i];
y[i] = x[i];
x[i] = k;
}
}
memset(G, 0, sizeof(G));
for(i = 0; i < n; i++)
{
for(j = 0; j < n; j++)
{
if(x[i] < x[j] && y[i] < y[j])
G[i][j] = 1; // G爲鄰接矩陣,G[i][j]表示第i個矩陣可以嵌套在第 j個矩陣裏面
}
}
memset(d,0,sizeof(d)); // d數組記錄的是每個矩陣能嵌套的最大矩陣
ans = 0;
for(i = 0; i < n; i++)
{
if(dp(i) > ans)
ans = dp(i);
}
printf("%d\n",ans);
}
return 0;
}