[题目]
设序列
L=<a1,a2,a3,⋯,an>
是长度为n的序列,
L
的一个递增序列描述为:
[分析]
常用的动态规划思想算法复杂度为 O(n2) ,改进后的采用二分查找的算法复杂度为 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;
}