zoukankan      html  css  js  c++  java
  • 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;
    }

  • 相关阅读:
    【每天都要看一下】
    【这里有别人的经验,也有好玩的发现】
    【WPF】Listbox模板内button点击选中当前listboxItem
    【WFP】弹出窗口不在win10 任务列表里显示的方法
    PSD路径转换为 WPF path 的data
    【WPF】Listbox内item的样式替换默认选中样式和鼠标滑过样式
    【WPF】ListBox1内嵌套ListBox2 2的滑轮滚动阻止1的滚动解决方法
    【C#】文本框拼音检索汉字
    【WPF】Datagrid显示最低下一跳
    【C#】绝对随机数
  • 原文地址:https://www.cnblogs.com/cute/p/15064210.html
Copyright © 2011-2022 走看看