这次的题目 , 我最初是想用 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\n",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\n",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\n",maxn); } return 0; }