[ACM_动态规划] 嵌套矩形

问题描述:有n个矩阵,每个矩阵可以用两个整数a,b来表示 ,表示他的长和宽,矩阵X (a,b) 可以 嵌套 到Y (c,d) 里面当且仅当 a < c &&  b < d  ||  a < d && b < c . 选出最多这种矩阵。先输出最多的数量,在输出最小字典序路径。
问题分析:本题是DAG(有向无环图)最长路问题,设d[i]为以i结尾的最长链的长度,则状态转移方程为:d[i]=max{0,d[j]|矩形j可以嵌套在矩形i中}+1 ;这里用map[i][j]存储i可嵌入j中
#include<iostream>
#include<algorithm>
using namespace std;
#define maxn 1000+5

class Rect{
public:
    int length;
    int width;
};
bool ok(Rect& a,Rect& b){          //嵌套关系判定函数
    return (a.length<b.length && a.width<b.width)
            ||(a.length<b.width && a.width<b.length);
}


int d[maxn],n,map[maxn][maxn];    //d[]用来存储以i结尾的最大长度,map[i][j]表示i可嵌套在j中
Rect rect[maxn];

int dfs(int cur)                  //深搜,记忆化搜索
{
    if( d[cur] > 0) return d[cur];//已经找过的直接输出
    d[cur] = 1;                   //没找的先付初值1,然后深搜寻找
    for(int i=1;i<=n;i++)
    {
        if( map[cur][i] && d[cur] < dfs(i)+1)
        {
            d[cur] = dfs(i)+1;
        }
    }
    return d[cur];
}
void out(int i)                   //反向追踪找到选取图形的标号
{
    cout << i << " ";
    for(int j=1;j<=n;j++)
    {
        if( map[i][j] && d[i] == d[j]+1)
        {
            out(j);
            break;
        }
    }
}

int main(){
    
    for(;cin>>n && n;){

        int i,j;
        
        for(i=1;i<=n;i++){                           //输入
            cin>>rect[i].length>>rect[i].width;
        }

        memset(map,0,sizeof(map));                   //构造一个嵌套关系的邻接矩阵
        for(i=1;i<=n;i++)
            for(j=1;j<=n;j++)
                if(ok(rect[i],rect[j]))
                    map[i][j]=1;

        memset(d,0,sizeof(d));                       //深搜记忆化完成d[]表
        for(i=1;i<=n;i++){
            dfs(i);
        }


        int max=0,ds;                                //找出d[]的最大值并用ds存储尾链位置
        for(i=1;i<=n;i++){
            if(max<d[i]){
                max=d[i];
                ds=i;
            }
        }

        cout<<max<<'\n';
        out(ds);cout<<'\n';
    }
}

            


        
View Code

 

posted @ 2013-07-27 11:51  beautifulzzzz  阅读(470)  评论(0编辑  收藏  举报