[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'; } }