您的位置:首页 > 其它

最大递增子序列问题

2015-07-17 22:11 302 查看

[题目]

设序列L=<a1,a2,a3,⋯,an>L = < a_1, a_2, a_3, \cdots, a_n >是长度为n的序列,LL的一个递增序列描述为:<ai1,ai2,⋯,aik>, 其中下标序列 <i1,i2,⋯,ik>< i_1, i_2, \cdots, i_k>是递增的, 子序列<ai1,ai2,⋯,aik>< a_{i1}, a_{i2}, \cdots, a_{ik}> 也是递增的,求此递增序列的长度为 k。

[分析]

常用的动态规划思想算法复杂度为O(n2)O(n^2),改进后的采用二分查找的算法复杂度为O(nlogn)O(nlogn)。具体分析过程参见下面的博客,讲解的很详细,易懂:最大递增子序列问题

我实现的核心代码如下:

#include <iostream>
using namespace std;
int main(){
int a[10] = {1,3,4,2,7,5,9,6,8,10};     //待测试数组
int len=0,t[10];        //t[递增子序列长度]=结尾处的最小值
t[1]=a[0];      //初始化
len=1;          //记录当前的最大递增子序列长度
int l,p,r;      //二分法的下界、中点、上界
for(int i=1; i<10; i++){
l=1;
r=len;
while(l<=r){    //二分查找
p=(l+r)/2;
if(t[p]<a[i])
l=p+1;
else
r=p-1;
}
t[l]=a[i];
if(l>len)
len++;
}
cout<<len<<endl;
return 0;
}


杭电oj(1025)-Constructing Roads In JGShining’s Kingdom应用的代码如下:

#include <iostream>
#include <stdio.h>
#include <algorithm>
using namespace std;

#define MAX 500010

typedef struct roads{
int pool;
int rich;
};

roads rd[MAX];
int t[MAX];

bool cmp(roads a, roads b){
if(a.pool < b.pool)
return true;
return false;
}

int main(){
int N,num=1;
freopen("input","r",stdin);
while(scanf("%d",&N)!=EOF){
for(int i=0; i<N; i++)
scanf("%d%d",&rd[i].pool,&rd[i].rich);   //注意这里要用scanf,使用cin会超时
sort(rd,rd+N,cmp);
t[1]=rd[0].rich;
int len=1;
int l,m,r;
for(int i=1; i<N; i++){
l=1;
r=len;
while(l<=r){
m=(l+r)/2;
if(t[m] < rd[i].rich)
l=m+1;
else
r=m-1;
}
t[l]=rd[i].rich;
if(l>len)
len++;
}
printf("Case %d:\n",num++);
if(len==1)
printf("My king, at most %d road can be built.\n\n",len);
else
printf("My king, at most %d roads can be built.\n\n",len);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: