【题意】
有n个矩形,每个矩形都有长和宽,表示为a和b
矩形X(a,b)可以镶嵌在矩形Y(c,d)中当且仅当a<c , b<d 或者 a<d , b<c (相当于把矩形X旋转90°)
求出能嵌套在一个里面的最多数
分析:可将当前状态视为可包含该矩形(该点)的最多矩形数量(最长路长度),即状态可转移为在可包含该矩形的矩形中可被最多矩形包含的矩形(即从另一个点出发的最长路)加一。若将该点状态表示为d(i),则状态转移方程为:d(i)=max{d(j)+1|}(j为某个矩阵对应点)
然后该题的另一个问题在于如何建立便于状态转移的多叉树,而这里提供一个不错的办法:建立一个2*2矩阵,纵下标代表各个状态对应点,横坐标供对应状态点标记,再令开一个一维数组,横坐标也为代表状态对应点,然后在设下标为0的点为d(i),开始搜索符合的矩阵点,符合时在二维数组的对应横坐标进行标记,最终在一维数组里保存该路长度,以达到记忆化搜索的目的
记忆化搜索DP:
#include<stdio.h>
#include<string.h>
int b[1010][1010],c[1010];
int max(int a, int b)
{
return a > b ? a : b;
}
int dp(int a, int n)
{
int j;
if (c[a] > 0)
return c[a];
c[a] = 1;
for (j = 0;j < n;j++)
{
if (b[a][j])
c[a] = max(c[a], dp(j, n)+1);
}
return c[a];
}
int main()
{
int n,i,j,m,x[1010],y[1010];
while (scanf("%d", &n) != EOF)
{
memset(c, 0, sizeof c);
memset(b, 0, sizeof b);
for (i = 0;i < n;i++)
scanf("%d%d", &x[i], &y[i]);
for (i = 0;i < n;i++)
{
for (j = 0;j < n;j++)
{
if ((x[i]>x[j]&&y[i]>y[j])||(x[i]>y[j]&&y[i]>x[j]))
b[i][j] = 1;
}
}
for (i = 0, m = 0;i < n;i++)
m = max(m, dp(i,n));
printf("%d\n", m);
}
return 0;
}