最長路問題

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


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章