首页 > 代码库 > POJ 1631 Bridging signals
POJ 1631 Bridging signals
题意:给出许多连线,要你删除一些使得剩下的连线最多且不想交,抽象出来就是最长上升序列问题(LIS)
LIS有两种经典解法,一种是DPO(N^2)的时间复杂度,还有一种二分O(NlogN)的时间复杂度。
第一种方法:
推荐题目PKOJ2533 ——Longest Ordered Subsequence 裸LIS
#include <iostream> #include<stdio.h> #include<string> #include<cstring> #include<cmath> #define N 2222//最长上升子序列,n^2算法 using namespace std; int dp[N]; int a[N]; int main() { int n; while(~scanf("%d",&n)) { memset(dp,0,sizeof dp); for(int i=1;i<=n;i++) scanf("%d",&a[i]); dp[1]=1;int ans=1; for(int i=2;i<=n;i++) { int m=0; for(int j=1;j<i;j++) { if(dp[j]>m&&a[i]>a[j]) m=dp[j]; } dp[i]=m+1; if(ans<dp[i]) ans=dp[i]; } printf("%d\n",ans); } return 0; }
第二种方法:
POJ1631,给的数据40000,直接做的话会超时,所以要用二分来做
http://www.docin.com/p-540470161.html 豆丁上把这种方法讲解的很好的一个PPT,看了就懂
#include <iostream> #include<stdio.h> #include<string> #include<cstring> #include<cmath> #include<algorithm> #define N 45000 using namespace std; int a[N]; int ans[N];//注意,ans数组储存的不是LIS,而是对应长度LIS的最小末尾 int len; int binary_search(int i) { int le,ri,mid; le=0;ri=len; while(le<ri) { mid=(ri+le)/2; if(ans[mid]>=a[i]) ri=mid; else le=mid+1; } return le; } int main() { int n; int p; while(~scanf("%d",&n)) { while(n--) { scanf("%d",&p); for(int i=1;i<=p;i++) scanf("%d",&a[i]); ans[1]=a[1]; len=1; for(int i=1;i<=p;i++) { if(ans[len]<a[i]) ans[++len]=a[i]; else { int pos=binary_search(i); ans[pos]=a[i]; } } printf("%d\n",len); } } return 0; }
有关的题目推荐:POJ 1887 POJ 1609
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。