定義:最長路一般用在DAG上,也即爲從DAG上的某點到大另外一點走的最長路徑
應用舉例:嵌套矩形
有n個矩形,每個矩形用兩個整數a,b描述,分別表示長和寬,矩形X(a,b)可以嵌套到矩形X(c,d)內當且僅當a<c, b<d,也可以通過選擇矩形得到嵌套關係,即a<d,b<c,現在的問題是求出儘量多的矩形,使得前面的矩形可以嵌套在所有後面的矩形內。
推廣:二維情況可以推廣到n維
解答:首先講矩形嵌套關係定義爲有向圖的邊,這樣就可以建立一個有向圖DAG,然後求DAG上的最長路即可
最長路的求法:若i->j有邊,則d[j] = d[i] +1,枚舉所有可以到達j的點,求最大值即可
下面給出嵌套問題的n爲情況的代碼
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define K 30
#define N 10
int boxes[K][N];
int G[K][K];
int d[K];
bool Nest(int s, int e, int n)
{
int i;
for (i = 0; i < n; i++)
if (boxes[s][i] >= boxes[e][i])
break;
if (i < n)
return false;
else
return true;
}
int dp(int s, int k)
{
if (d[s] > 0)
return d[s];
d[s] = 1;
for (int i = 0; i < k; i++)
{
if (G[i][s])
d[s] = d[s] > dp(i, k) + 1 ? d[s] : d[i] + 1;
}
return d[s];
}
void PrintPath(int s, int e, int k)
{
int i;
for (i = 0; i < k; i++)
if (G[i][s] && d[i] + 1 == d[s])
break;
if (i < k)
PrintPath(i, e, k);
printf("%d", s + 1);
if (s == e)
printf("\n");
else
printf(" ");
}
int main(void)
{
int k, n;
while (scanf("%d%d", &k, &n) != EOF)
{
int i, j;
for (i = 0; i < k; i++)
{
for (j = 0; j < n; j++)
scanf("%d", &boxes[i][j]);
sort(boxes[i], boxes[i] + n);
}
memset(G, 0, sizeof(G));
memset(d, -1, sizeof(d));
for (i = 0; i < k; i++)
{
for (j = 0; j < k; j++)
{
if (Nest(i, j, n))
G[i][j] = 1;
}
}
int index = 0;
for (i = 0; i < k; i++)
{
int len = dp(i, k);
if (d[i] > d[index])
{
index = i;
}
}
printf("%d\n", d[index]);
PrintPath(index, index, k);
}
return 0;
}