9.2 嵌套矩形问题

矩形之间的"可嵌套"关系是一个典型的二元关系,二元关系可以用图来建模。如果矩形X可以嵌套在矩形Y里,我们就从X到Y连一条有向边。这个有向图是无环的,因为一个矩形无法直接或间接地嵌套在自己的内部。换句话说,它是一个DAG。这样,我们的任务便是求DAG上的最长路径。

可画图分析一下。


打印字典序最小的一个解


/*
  *
嵌套矩形问题
描述#
有n个矩形,每个矩形可以用a,b来描述,表示长和宽。矩形X(a,b)可以嵌套在矩形Y(c,d)中当且仅当a<c,b<d或者b<c,a<d(相当于旋转X90度)。例如(1,5)可以嵌套在(6,2)内,但不能嵌套在(3,4)中。你的任务是选出尽可能多的矩形排成一行,使得除最后一个外,每一个矩形都可以嵌套在下一个矩形内。

输入#
第一行是一个正正数N(0<N<10),表示测试数据组数,
每组测试数据的第一行是一个正正数n,表示该组测试数据中含有矩形的个数(n<=1000)
随后的n行,每行有两个数a,b(0<a,b<100),表示矩形的长和宽

输出#
每组测试数据都输出一个数,表示最多符合条件的矩形数目,每组输出占一行

样例输入#

1
10
1 2
2 4
5 8
6 10
7 9
3 1
5 8
12 10
9 7
2 2
样例输出#
5

*/

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;

const int maxn=1000+5;

int G[maxn][maxn];// 图用邻接矩阵保存

int w[maxn];
int h[maxn];

int d[maxn];

int T;
int N;

// 设d(i)表示从结点i出发的最长路长度
int dp(int i)
{
     int &ans=d[i];
     if(ans>0)
         return ans;
     ans=1;
     for(int j=0;j<N;j++)
     {
         if(G[i][j])
         {
             ans=max(ans, dp(j)+1);
         }
     }
     return ans;
}

void print_ans(int i)
{
     cout<<i<<endl;
     for(int j=0;j<N;j++)
         if(G[i][j] && d[i]==d[j]+1)
         {
             print_ans(j);
             break;
         }

}

int main()
{
     cin>>T;
     while(T--)
     {
         // 输入矩形长宽
         cin>>N;
         memset(G, 0, sizeof(G));
         memset(d, 0, sizeof(d));
         for(int i=0;i<N;i++)
         {
             cin>>w[i]>>h[i];
             if(w[i]>h[i]) swap(w[i], h[i]);
         }
         // 构建DAG
         for(int i=0;i<N;i++)
             for(int j=0;j<N;j++)
             {
                 if(w[i]<w[j] && h[i]<h[j]) G[i][j]=1;
             }

        //dp
         int ans=0;//嵌套长度
         int best=0;//记录从哪个开始
         // 没有确定路径的起点和终点,所以需要遍历所有起点(可以把任意矩形放在第一个和最后一个)
         for(int i=0;i<N;i++)
         {
             int t=dp(i);
             if(t>ans)
             {
                 ans=t;
                 best=i;
             }
         }
         cout<<ans<<endl;
         print_ans(best);
     }

    return 0;
}




打印所有解


/*
  *
嵌套矩形问题
描述#
有n个矩形,每个矩形可以用a,b来描述,表示长和宽。矩形X(a,b)可以嵌套在矩形Y(c,d)中当且仅当a<c,b<d或者b<c,a<d(相当于旋转X90度)。例如(1,5)可以嵌套在(6,2)内,但不能嵌套在(3,4)中。你的任务是选出尽可能多的矩形排成一行,使得除最后一个外,每一个矩形都可以嵌套在下一个矩形内。

输入#
第一行是一个正正数N(0<N<10),表示测试数据组数,
每组测试数据的第一行是一个正正数n,表示该组测试数据中含有矩形的个数(n<=1000)
随后的n行,每行有两个数a,b(0<a,b<100),表示矩形的长和宽

输出#
每组测试数据都输出一个数,表示最多符合条件的矩形数目,每组输出占一行

样例输入#

1
10
1 2
2 4
5 8
6 10
7 9
3 1
5 8
12 10
9 7
2 2
样例输出#
5
0 1 2 3 7
0 1 2 4 7
0 1 2 8 7
0 1 6 3 7
0 1 6 4 7
0 1 6 8 7
5 1 2 3 7
5 1 2 4 7
5 1 2 8 7
5 1 6 3 7
5 1 6 4 7
5 1 6 8 7

*/

#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
using namespace std;

const int maxn=1000+5;

int G[maxn][maxn];

int w[maxn];
int h[maxn];

int d[maxn];

int T;
int N;

int dp(int i)
{
     int &ans=d[i];
     if(ans>0)
         return ans;
     ans=1;
     for(int j=0;j<N;j++)
     {
         if(G[i][j])
         {
             ans=max(ans, dp(j)+1);
         }
     }
     return ans;
}

int path[maxn];//记录递归过程中的路径
void print_ans_all(int i, int cur)
{
     path[cur]=i;
     if(d[i]==1)//说明到最后一个矩形
     {
         for(int j=0;j<=cur;j++)
         {
             cout<<path[j]<<" ";
         }
         cout<<endl;
         return;
     }
     for(int j=0;j<N;j++)
         if(G[i][j] && d[i]==d[j]+1)
         {
             print_ans_all(j, cur+1);
//            break;
         }

}

void print_ans(int i)
{
     cout<<i<<" ";
     for(int j=0;j<N;j++)
         if(G[i][j] && d[i]==d[j]+1)
         {
             print_ans(j);
             break;
         }

}

int main()
{
     cin>>T;
     while(T--)
     {
         // 输入矩形长宽
         cin>>N;
         memset(G, 0, sizeof(G));
         memset(d, 0, sizeof(d));
         for(int i=0;i<N;i++)
         {
             cin>>w[i]>>h[i];
             if(w[i]>h[i]) swap(w[i], h[i]);
         }
         // 构建DAG
         for(int i=0;i<N;i++)
             for(int j=0;j<N;j++)
             {
                 if(w[i]<w[j] && h[i]<h[j]) G[i][j]=1;
             }

        //dp
         int ans=0;//嵌套长度
         int best=0;//记录从哪个开始
         for(int i=0;i<N;i++)
         {
             int t=dp(i);
             if(t>ans)
             {
                 ans=t;
                 best=i;
             }
         }
         cout<<ans<<endl;

        for(int i = 0; i <= N; i++)
           if(ans == dp(i)) print_ans_all(i, 0);

//        print_ans(best);
     }

    return 0;
}

posted on 2021-07-27 09:21  katago  阅读(119)  评论(0编辑  收藏  举报