您的位置:首页 > 其它

DP经典应用(四)二维最长上升子序列问题——矩形嵌套问题

2017-04-09 19:33 253 查看

矩形嵌套问题

问题描述:输入多个矩形的长和宽。矩形X(a,b)可以嵌套在矩形Y(c,d)中当且仅当a < c,b < d或者b < c,a < d,任务是选出尽可能多的矩形排成一行,使得除了最后一个之外,每一个矩形都可以嵌套在下一个矩形内求出最多嵌套矩形的个数。

注意加粗的一段话,就要求我们必须先排序

样例输入:

1
10
1 2
2 4
5 8
6 10
7 9
3 1
5 8
12 10
9 7
2 2


样例输出:

5


分析:

这个问题是不是和最长递增子序列的问题十分类似。

只不过这个子序列的数不只是一个数,而是长和宽罢了。

所以只要会转换一下就十分简单了。

依然按照分析动态规划的3个步骤:

按照3个步骤:

1.刻画最优解结构特征:

定义dp[i]为以第i个矩形pi为末尾的整个矩形序列中能够被嵌套的最多数目

2.递归地定义最优解的值:

以第i个矩形pi为末尾元素的序列是:

1.只包含第i个矩形pi的序列

2.如果满足j < i 并且 pj.l < pi.l && pj.w < pi.w这个条件的以pj为末尾的序列末尾再加上pi后得到的新序列。

这两者之一。

所以得到此递推式:

dp[i] = max(dp[i],dp[j]+1) (j < i 且 pj.l < pi.l && pj.w < pi.w)

3.计算最优解的值(递推)

代码如下:

#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 100;

struct P{
int l,w;
}p[maxn];

int max(int a,int b)
{
return a>b?a:b;
}
int min(int a,int b)
{
return a<b?a:b;
}

int cmp(const P& a,const P& b)
{
if(a.l<b.l) return 1;
else if(a.l==b.l&&a.w<b.w) return 1;
else return 0;
}

int dp[maxn];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
int a,b;
scanf("%d%d",&p[i].l,&p[i].w);
a = max(p[i].l,p[i].w);
b = min(p[i].l,p[i].w);
p[i].l = a; p[i].w = b;//长大于宽
}
sort(p,p+n,cmp);
for(int i=0;i<n;i++)
{
dp[i] = 1;
for(int j=0;j<=i;j++)
{
if(p[j].l<p[i].l&&p[j].w<p[i].w)
{
dp[i] = max(dp[i],dp[j]+1);
}
}
}
int ans=dp[0];
for(int i=0;i<n;i++)
{
if(ans<dp[i])
ans = dp[i];
}
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: