HDU 1025 高效最长上升子序列(二分查)
2012-09-19 10:41
211 查看
用到了LIS(Longest Increasing Subsequence)最长上升(不下降)子序列,它有两种算法复杂度为O(n*logn)和O(n^2)。前者使用二分查找,后者朴素查找。它的算法大致思路:设置两个a,b数组,a数组存储数据,b数组存储最长不降序序列。此算法关键在于设计二分查找。
刚开始用到了朴素dp算法,果断超时,超时代码为:
改进后,用到二分查找,一直莫名奇妙Wa,还没找到原因,数据上有问题?
Wa代码:
最后是AC代码,源于/article/6994645.html
其实显然这个数组开小了,不过能ac。
改天继续查找Wa原因
刚开始用到了朴素dp算法,果断超时,超时代码为:
#include <iostream> #include <algorithm> using namespace std; const int Max = 500010; int dp[Max]; typedef struct { int x, y; } Node; Node node[Max]; int cmp(const void * a, const void * b) { return (*(Node*)a).x - (*(Node*)b).x; } int main() { int n; int t = 1; while(cin >> n) { memset(dp, 0, sizeof(dp)); for(int i = 0; i < n; i++) scanf("%d%d", &node[i].x, &node[i].y); //qsort(node, n, sizeof(Node), cmp); /*for(int i = 0; i < n; i++) printf("%d %d\n", node[i].x, node[i].y);*/ for(int i = 0; i < n; i++) { dp[i] = 1; for(int j = i - 1; j >= 0; j--) { if(dp[j] + 1 > dp[i] && node[i].y > node[j].y) dp[i] = dp[j] + 1; } } int max = 0; for(int i = 0; i < n; i++) if(dp[i] > max) max = dp[i]; printf("Case %d:\n", t++); printf("My king, at most %d road can be built.\n\n", max); } return 0; }
改进后,用到二分查找,一直莫名奇妙Wa,还没找到原因,数据上有问题?
Wa代码:
#include <iostream> #include <algorithm> using namespace std; const int Max = 500010; int dp[Max]; int B[Max]; typedef struct { int x, y; } Node; Node node[Max]; int cmp(const void * a, const void * b) { return (*(Node*)a).x - (*(Node*)b).x; } int main() { freopen("1025.txt", "r", stdin); int n; int t = 1; while(cin >> n) { memset(dp, 0, sizeof(dp)); memset(B, 0, sizeof(B)); for(int i = 0; i < n; i++) scanf("%d%d", &node[i].x, &node[i].y); qsort(node, n, sizeof(Node), cmp); B[0] = -1000; B[1] = node[0].y; int len = 1; int p, r, m; for(int i = 1; i < n; i++) { p = 1; r = len; while(p <= r) { m = (p+r) / 2; if(B[m] < node[i].y) p = m + 1; else r = m - 1; } B[p] = node[i].y; if(p > len) len = p; } printf("Case %d:\n", t++); printf("My king, at most %d road can be built.\n\n", len); } return 0; }
最后是AC代码,源于/article/6994645.html
#include<stdio.h> int dp[50005],a[50005]; int Lis(int n) { int len=1,i,low,high,mid; dp[1]=a[1]; for(i=2;i<=n;i++) { low=1; high=len; while(low<=high) { mid=(low+high)/2; if(a[i]>dp[mid]) low=mid+1; else high=mid-1; } dp[low]=a[i]; if(low>len) len=low; } return len; } int main() { int n,x,y,i,ans,k=1; while(scanf("%d",&n)!=EOF) { for(i=0;i<n;i++) { scanf("%d%d",&x,&y); a[x]=y; } ans=Lis(n); printf("Case %d:\n",k++); if(ans==1) printf("My king, at most 1 road can be built.\n"); else printf("My king, at most %d roads can be built.\n",ans); printf("\n"); } return 0; }
其实显然这个数组开小了,不过能ac。
改天继续查找Wa原因
相关文章推荐
- HDU 1025 DP+二分求解最长上升序列
- 【二分】【最长上升子序列】HDU 5489 Removed Interval (2015 ACM/ICPC Asia Regional Hefei Online)
- 暑期dp46道(16)hdoj 1025 Constructing Roads In JGShining's Kingdom最长上升子序列(二分)
- hdu 1025 二分查找+最长上升子序列
- hdu 1025 Constructing Roads In JGShining's Kingdom 最长上升序列
- 【二分】【最长上升子序列】HDU 5489 Removed Interval (2015 ACM/ICPC Asia Regional Hefei Online)
- hdu 1025 Constructing Roads In JGShining's Kingdom 最长上升序列nlogn
- hdu 1025 Constructing Roads In JGShining's Kingdom【即求最长上升子序列】
- hdu 1025 Constructing Roads In JGShining's Kingdom 最长上升序列nlogn
- hdu 1025 Constructing Roads In JGShining's Kingdom【即求最长上升子序列】
- 动态规划之编号动态规划:hdu 1025(dp+二分 求最长上升子序列)
- DP_简单DP最长上升子序列[n*lg(n)](HDU_1025)
- 【动态规划】【二分】【最长上升子序列】HDU 5773 The All-purpose Zero
- 最长上升子序列 HDU 1025 Constructing Roads In JGShining's Kingdom
- hdu 5256 序列变换(最长上升子序列&&二分)
- HDU 1025 最长上升子序列变形 (dp+二分)
- HDU 1025-Constructing Roads In JGShining's Kingdom(最长上升子序列 NlogN复杂度)
- 【动态规划】【二分】【最长上升子序列】HDU 5773 The All-purpose Zero
- 最长上升子序列(LIS)(HDU 1025)
- hdu 1025 Constructing Roads In JGShining's Kingdom(最长上升序列n*logn算法)