本来很早就想学这个东西,都说是动态规划的基础,可是白书上一笔带过(真心不推荐白书!!! 个人感觉就是渣!)、不三不四,网上找的又杂七杂八,无奈现在才去看,白书真是毁了一个人学算法的兴趣啊、、、、
还有就是,今天才发现,所谓的百度百科,在这方面,真的好不专业、、!!
DAG图:在图论中,如果一个有向图无法从某个顶点出发经过若干条边回到该点,则这个图是一个有向无环图(DAG图)。
我们这边以嵌套矩形为例子:
有n个矩阵,每个矩阵可以用两个整数a,b描述,表示它的长和宽。矩阵X(a,b)可以嵌套在矩阵Y(c,d)中当且仅当a<c,b<d,或者b<c,a<d。
我们可以用图来建立模型,假设图形Q ,可以嵌套在W 中,那么就从Q 到 W 连一条有向边,这个有向图是无环的,即DAG图,因为一个矩形无法直接或间接地嵌套在自己的内部。如此建立好模型后,就是求DAG上的最长的路径了,那要怎么求呢,我们可以假设把每一个点的值赋为1, 然后用DP,搞上去,最后的就是最大的路径了,另外一种,就是我在网上或者书上看到的记忆化搜索。
关于优化:1. 可以先对边进行排序,可是感觉对复杂度上没啥区别啊(- - # )2. 使用队列,可以减小空间复杂度、、
下面是代码:
题目 NYOJ 16 嵌套矩阵 链接:http://acm.nyist.net/JudgeOnline/status.php?pid=16
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 1010
int G[maxn][maxn];
int a[maxn];
int b[maxn];
int d[maxn];
int n;
int dp(int i)
{
int &ans = d[i]; // 记忆化的关键
if (ans > 0)
return ans;
ans = 1;
for(int j = 1; j <= n; ++j)
{
if(G[i][j])
ans = max(ans, dp(j)+1);
}
return ans;
}
int main()
{
int t;
while(~scanf("%d", &t))
{
while(t--)
{
scanf("%d", &n);
for(int i = 1; i <= n; ++i)
scanf("%d%d", &a[i], &b[i]);
memset(G, 0, sizeof(G));
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= n; ++j)
if( (a[i] > a[j] && b[i] > b[j]) || ( a[i] > b[j] && b[i] > a[j] ) )
G[i][j] = 1;
int ans = -1;
int tmp;
for (int i = 1; i <= n; ++i)
{
tmp = dp(i);
ans = max(ans, tmp);
}
printf("%d\n", ans);
}
}
}