矩形嵌套

这次的题目 , 我最初是想用 NlogN 的那个算法去做 结果数值覆盖那里出了问题 , 由于 : 1 ,我自己的理解不够 . 2 :算法自身的局限 , 导致是在想不出来 解决的办法 , 先把代码附上 , 这次还是用的 lower_bound 代码长度还行 ,

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<math.h>
 4 #include<iostream>
 5 #include<algorithm>
 6 #include<queue>
 7 #include<vector>
 8 #include<set>
 9 #include<stack>
10 #include<string>
11 #include<sstream>
12 #include<map>
13 #include<cctype>
14 #include<limits.h>
15 using namespace std;
16 struct node
17 {
18     int x,y;
19 }a[15];
20 bool cmp(node a,node b)
21 {
22     if(a.x<b.x)
23         return true;
24     else
25         if(a.x==b.x&&a.y<b.y)
26             return true;
27     return false;
28 }
29 int x[15],y[15],dpx[15],dpy[15];
30 int main()
31 {
32     int t,n;
33     scanf("%d",&t);
34     while(t--)
35     {
36         scanf("%d",&n);
37         for(int i=0;i<n;i++)
38         {
39             int x1,y1;
40             scanf("%d%d",&x1,&y1);   // 让 x 尽量的大 .
41             if(x1>y1)
42                 swap(x1,y1);
43             a[i].x=x1,a[i].y=y1;   //  尽量的 让 x  大
44         }      //  然后开始 排序
45         sort(a,a+n,cmp);   //   排序之后  就  从大到小找 递减子序列
46         for(i=0;i<n;i++)
47         {
48             x[i]=a[i].x,y[i]=a[i].y;    //  将他 输入到  两个数组当中 开始 用 lower_bound
49         }
50         int num=0,locationx,locationy;
51         for(i=0;i<n;i++)
52         {
53             locationx=lower_bound(dpx,dpx+num,x[i])-dpx;
54             locationy=lower_bound(dpy,dpy+num,y[i])-dpy;
55             if(locationx==locationy)
56             {
57                 dpx[locationx]=x[i];
58                 dpy[locationy]=y[i];
59                 num=locationx+1>num?locationx+1:num;
60             }
61         }
62         printf("%d
",num);
63     }
64     return 0;
65 }

 

这一组测试数据出了问题.
5
15 94
13 11
33 12
9 49
62 14

  可以发现  按照 x 或 y 中的一个数字排序的时候 另一个数字的大小 会特别的大 , ,然后 这样的顺序就不是 , 能嵌套最多的 顺序了 ,  可以发现这一道题  , 如果做的时候  所依据的算法  要依赖顺序的话 是 十分  让人难受的  ,     看了看 别人做的 , 大部分都是N^2 的时间复杂度  .  想起来自己以前做的 最少导弹拦截系统 , 也是不用考虑

最早的时候我想的是  将他们排序 , 排序的函数是

bool cmp(node a,node b)
{
    if(a.x<b.x)
        return true;
    else
        if(a.x==b.x&&a.y<b.y)
            return true;
    return false;
}

然后用用二分法  ,  按照最长递增子序列的方法 , 找出来最长递增 嵌套 矩形 .  但是在实现的时候 和 一维的 最长递增子序列 有很大的区别    下面附上 一维最长递增子序列的 核心代码  . 

for(int i=0;i<n;i++)
{
    scanf("%d",&b);
    location=lower_bound(dp,dp+num,b)-dp;    //在 已经有序的数组中二分查找
    dp[location]=b;
    num=location+1>num?location+1:num;
}

二维的话  , 代码如下 

 1 for(i=0;i<n;i++)
 2 {
 3     locationx=lower_bound(dpx,dpx+num,x[i])-dpx;
 4     locationy=lower_bound(dpy,dpy+num,y[i])-dpy;
 5     if(locationx==locationy)
 6     {
 7         dpx[locationx]=x[i];
 8         dpy[locationy]=y[i];
 9         num=locationx+1>num?locationx+1:num;
10     }
1

 将这两个 代码进行对比可以发现 ,第一个 代码之中的 数据元素都能进入 dp 数组 然而第二个 代码可以看出 , 有些数据元素 不能进入 dp数组 , 就这样导致了错误。 , 具体错误 可以 用我上面 给出的 完整代码和 数据 进行 调试 看出来 。 然后我就又想了想 , 发现这个代码不正确的原因就是 排序的错误  ,  如果排序正确的话 , 是不会 出现这样的情况的   。  

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#include<set>
#include<stack>
#include<string>
#include<sstream>
#include<map>
#include<cctype>
#include<limits.h>
using namespace std;                //  奇妙奇妙真奇妙
struct node
{
    int x,y;                      //        按照 最少拦截系统的思路来说  ,
};
bool cmp(node a,node b)
{
    if(a.x<b.x)
        return true;
    else
        if(a.x==b.x&&a.y<b.y)
            return true;
    return false;
}
int main()
{
    int t,n,dp[1005];
    node a[1005];
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(int i=0;i<n;i++)
        {
            int x1,y1;
            scanf("%d%d",&x1,&y1);   // 让 x 尽量的大 .
            if(x1>y1)
                swap(x1,y1);
            a[i].x=x1,a[i].y=y1;   //  尽量的 让 x  大
        }      //  然后开始 排序
        sort(a,a+n,cmp);   //   排序之后  就  从大到小找 递减子序列
        for(int i=0;i<=n;i++)
            dp[i]=1;
        for(int i=1;i<n;i++)
        {
            for(int j=0;j<i;j++)
            {
                if(a[i].x>a[j].x&&a[i].y>a[j].y&&dp[i]<dp[j]+1)
                    dp[i]=dp[j]+1;
            }
        }
        int maxn=INT_MIN;
        for(int i=0;i<n;i++)
            maxn=max(maxn,dp[i]);
        printf("%d
",maxn);
    }
    return 0;
}

 下面是玉民大大写的  ,  一道题的解法还是很多的 , 有时候不能想的 太复杂了 ,  这就是一个 很简单的想法   

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#include<set>
#include<stack>
#include<string>
#include<sstream>
#include<map>
#include<cctype>
#include<limits.h>
using namespace std;
struct node
{
    int x,y;
}a[1005];
bool cmp(node a,node b)
{
    if(a.x<b.x)
        return true;
    return false;
}
int main()
{
    int t,n,dp[1005];
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(int i=0;i<n;i++)
        {
            int x1,y1;
            scanf("%d%d",&x1,&y1);   // 让 x 尽量的大 .
            if(x1>y1)
                swap(x1,y1);
            dp[i]=1;
            a[i].x=x1,a[i].y=y1;   //  尽量的 让 x  大
        }      //  然后开始 排序
        sort(a,a+n,cmp);   //   排序之后  就  从大到小找 递减子序列
        for(int i=1;i<n;i++)
        {
            for(int j=0;j<i;j++)
            {
                if(a[i].x>a[j].x&&a[i].y>a[j].y)
                    dp[i]=dp[i]>dp[j]+1?dp[i]:dp[j]+1;
            }
        }
        int maxn=INT_MIN;
        for(int i=0;i<n;i++)
            maxn=maxn>dp[i]?maxn:dp[i];
        printf("%d
",maxn);
    }
    return 0;
}

 

原文地址:https://www.cnblogs.com/A-FM/p/5431328.html