定义:最长路一般用在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;
}