嵌套矩阵——DAG动态规划

题目 2075: 矩阵嵌套
时间限制: 1Sec 内存限制: 128MB 提交: 259 解决: 54
题目描述
有 n 个矩形,每个矩形可以用 a,b来描述,表示长和宽。矩形 X(a,b)可以嵌套在矩形 Y(c,d)中当且仅当 a

(相当于旋转 90 度)。例如(1,5)可以嵌套在(6,2)内,但不能嵌套在(3,4)中。你的任务是选出尽可能多的矩形排成一行,

使得除最后一个外,每一个矩形都可以嵌套在下一个矩形内。
输入
第一行是一个正正数 N(0

每组测试数据的第一行是一个正正数 n,表示该组测试数据中含有矩形的个数 (n≤1000)。

随后的 n 行,每行有两个数 a,b(0

输出
每组测试数据都输出一个数,表示最多符合条件的矩形数目,每组输出占一行。
样例输入
1
10
1 2
2 4
5 8
6 10
7 9
3 1
5 8
12 10
9 7
2 2
样例输出
5

解题思路
矩形之间的嵌套是一个二元关系,由此联系到了邻接矩阵成图的理论,这个图应该是有方向的,因为能否被包含是单方面,故我们根据特性建立一个有向图。由此可得出,我们要求就是这个图(DAG)的最长路径。
状态转移方程: d(i)=max(d(j)+1|(i,j)属于E) 其中E为边的集合

#include 
#include 
#define MAX(a,b) ((a)>(b)?(a):(b))
//状态转移方程:d(i)=max(d(j)+1|(i,j)属于E) 其中E为边的集合
int arc[1001][1001];
int d[1001];  //记忆化数组,记得每次使用都要初始化为0

void CreatGraph(int a[],int b[],int n)
{
     
    int i,j;
    for(i=0;i<n;i++)
        for(j=0;j<n;j++)   //双向的故不从i+1开始
    {
     
        if( (a[i]<a[j]&&b[i]<b[j]) || (b[i]<a[j]&&a[i]<b[j]))   // X(a,b)Y(c,d) a
            arc[i][j]=1;
        else
            arc[i][j]=0;
    }
}

int dp(int i,int n)
{
     
    int j;
    //int &ans=d[i];//ans和d[i]共用一个地址即ans与d[i]为一个变量c++用法
    int *ans;
    ans=&d[i];  //用d保存着到以i为起始点的最长路径
    if(*ans>0) return *ans;
    *ans=1;
    for(j=0;j<n;j++)
      if(arc[i][j])
        {
     
            *ans=MAX(*ans,dp(j,n)+1);   //+1代表多一个矩形
        }
    return *ans;
}

int main()
{
     
    int T;
    scanf("%d",&T);
    while(T--)
    {
     
        int n,a[1001],b[1001],i,ans=0;
        scanf("%d",&n);
        for(i=0;i<n;i++)
            d[i]=0;  //初始化d
        for(i=0;i<n;i++)
            scanf("%d%d",&a[i],&b[i]);
        CreatGraph(a,b,n);
        for(i=0;i<n;i++)
            ans=MAX(ans,dp(i,n));   //各个点都可能作为起始点
        printf("%d\n",ans);
    }
    return 0;
}

你可能感兴趣的:(嵌套矩阵——DAG动态规划)