很模板的一道动归题,看过跟蓝书里的那道矩形嵌套的例题是一样的,就是换个包装而已。两个线段之间的关系要么能嵌套,要么不能,这种二值的属性一般可以考虑用有向图来表示,而且它不可能互相嵌套,所以无环,故转化成DAG问题,这道题变成求DAG上的最长路径。
用一维的dp数组就可以表示,dp[u]表示以i号点为起点的最长路径长度,然后用记忆化搜索对每个点都算一遍,找到最大的值就是最长路径长度。状态转移是,dp[u]=max{dp[v]+1|(u,v)为边}。由于还要输出路径,所以可以开个数组记录每个点的下一个点的位置。
#include <iostream>
#include <vector>
using namespace std;
vector<int> temp;
vector<vector<int> >v(500, temp);
int dp[500];
int nexts[500];
int l[500];
int r[500];
int d(int x)
{
if (dp[x] != 0)
return dp[x];
dp[x] = 1;
for (int i = 0;i < v[x].size();i++)
{
if (d(v[x][i]) + 1>dp[x])
{
dp[x] = d(v[x][i]) + 1;
nexts[x] = v[x][i];
}
}
return dp[x];
}
void print(int x)
{
if (nexts[x] == 0)
{
cout << x << endl;
return;
}
cout << x << " ";
print(nexts[x]);
}
int main()
{
int N;
cin >> N;
for (int i = 1;i <= N;i++)
{
cin >> l[i] >> r[i];
for (int j = 1;j < i;j++)
{
if (l[i]<l[j] && r[i]>r[j])
v[j].push_back(i);
if (l[j]<l[i] && r[j]>r[i])
v[i].push_back(j);
}
}
int maxs = 0, index = 0;
for (int i = 1;i <= N;i++)
{
if (d(i) > maxs)
{
maxs = d(i);
index = i;
}
}
cout << maxs << endl;
print(index);
}