嵌套矩阵问题

题目描述:

有n个矩形,每个矩形可以用两个整数来描述,表示它的长与宽。矩形X(a, b) 可以嵌套在矩形 Y(c, d) 中,当且仅当 a < c, b< d 或者 b < c, a < d (矩阵可以旋转90度)。你的任务是选出尽可能多的矩阵排成一行,使得每一个矩形(除最后一个矩阵)都可以嵌套在后一个矩形内。

注:如果有多解,矩形编号的数字尽量小。

解题思路:

这个题是DAG(有向无环图)上的最长路经问题。这个题是要我们求不固定起点的最长路经。

我们可以用动态规划来做,令d [ i ] 为从第i个矩形出发最长路长度。

可写出状态转移方程: d[ i ] = max( d[ i ] , dp( j ) + 1 )

要输出字典序最小的解,只需每次找寻下一个解的时候,从第一个矩形开始循环即可。

#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <string.h>
#define MAX 100
using namespace std;
struct mat{
    int l,w;
}; 
mat a[MAX];
int G[MAX][MAX];
int d[MAX];
int T,n;
int dp(int i){
    if(d[i])
        return d[i];
    d[i] = 1;//不要忘记这一步 
    for(int j = 1; j <= n; j++)
        if(G[i][j])
            d[i] = max(d[i],dp(j)+1);
    return d[i];
}
void display(int i){
    cout<<i<<" ";
    for(int j = 1; j <= n; j++){
        if(G[i][j] && d[i] == d[j] + 1){
            display(j);
            return;
        }
    }
}
int main()
{
    scanf("%d", &T);
    while(T--){
        memset(G,0,sizeof(G));
        memset(d,0,sizeof(d));
        scanf("%d", &n);
        for(int i=1;i<=n;i++){
            scanf("%d %d",&a[i].l, &a[i].w);
            for(int j=1;j<i;j++)
                if((a[j].l < a[i].l && a[j].w < a[i].w)||
                (a[j].l < a[i].w && a[j].w < a[i].l))
                    G[j][i] = 1;//j 可以被 i 覆盖
                else if((a[j].l > a[i].l && a[j].w > a[i].w)||
                (a[j].l > a[i].w && a[j].w > a[i].l))
                    G[i][j] = 1;
        }//DAG矩阵 G 构建完成 
        
        int max_i = 0;
        for(int i=1;i<=n;i++)
            if(dp(max_i) < dp(i))
                max_i = i;
        cout<<d[max_i]<<endl;
        display(max_i);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/woxiaosade/p/10336206.html