让a接在后面形成长于p(i)的最长递增子序列的元素不在数组B中,由命题2可知,这是不可i
能的,因为B[c]中存放的是最末元素最小的长度为c的最长递增子序列的最末元素,若a能接i在长度为L(L>p(i))的最长递增子序列后面,就应该能接在B[L]后面,那么就应该有p(i)=L,与L>p(i)矛盾。
因此一定有p(i)=f(i),命题得证。
算法的循环次数为n,每次循环二分查找用时logn,所以算法的时间复杂度为O(nlogn)。
这个算法在第二种算法的基础上得到了较好的改进。
本论文只给出了计算解的大小而没有给出构造解的方法,因为我认为计算解的大小的算法已
能给出对问题的本质认识,只要计算解大小的算法设计出,构造解就只是技术细节的问题了,而
我关心的是怎样对问题得到很好的认识而设计出良好的算法。
以上几种算法已用Java实现,都能得到正确的结果。
在设计和改进算法时用到了基本的算法设计和分析、证明的基本方法,很好
的锻炼了设计与分析算法的思维能力,让我从感性上认识到算法分析与设计的重要性,并且感受
了算法分析、设计和改进的乐趣。
【实验目的】
练习掌握动态规划算法。
【实验内容】
设计一个O(n*n)时间的算法,找出由n个数组成的序列的最长单调递增子序列。
【实验条件】
MicrosoftVisualC++6.0
【需求分析】
题目要求在O(n*n)的时间内找出n个数组成的序列的最长单调递增子序列,需要
用到排序算法,查找最长公共子序列的算法。
【设计原理】
将数组a复制到数组x,先用排序算法将数组x排序,在调用查找最长公共子序
列的算法求出数组a和数组x中的最长公共子序列,因为数组x是单调递增的,所以由此求出来的最长公共子序列就是题设所求的最长单调递增子序列。
【概要设计】
数据:
N:
数组元素个数。
a[N]:
用于存放数组。
X[N]:
复制数组a[N],并排序。
c[i][j]:
存储a和x的最长公共子序列的长度。
b[i][j]:
记录c[i][j]的值是由哪一个资问题的解得到的。
函数:
intPartition(inta[],intp,intt,intx);
//数组划分,将小于等于x的元素移到x左边,大于x的元素移到x右边。
voidSwap(int&x,int&y);
//交换元素x和y。
voidQuickSort(inta[],intp,intr);
//快速排序。
voidLCSL(intm,intn,int*x,int*y,int**c,int**b);
//计算最长公共子序列长度。
voidLCS(inti,intj,int*x,int**b);
根据b[i][j]的内容打印a,x数组的最长公共子序列。
【详细设计】
#include
#include
usingnamespacestd;
#defineN10
voidLCSL(intm,intn,int*x,int*y,int**c,int**b);//计算最长公共子
序列长度。
voidLCS(inti,intj,int*x,int**b);//根据b[i][j]的内容打印a,x数组
的最长公共子序列。
voidQuickSort(inta[],intp,intr);//快速排序。
intPartition(inta[],intp,intt);//数组划分,将小于等于x的元素移到
x左边,大于x的元素移到x右边。
voidSwap(int&x,int&y);//交换元素x和y。
//计算最长公共子序列长度voidLCSL(intm,intn,int*x,int*y,intc[][N],intb[][N])
{
c[0][0]=0;
inti,j;
for(i=1;i<=m;i++)
c[i][0]=0;
for(i=1;i<=n;i++)
c[0][i]=0;
for(i=1;i<=m;i++)
for(j=1;j<=m;j++)
{
if(x[i]==y[j])
{
c[i][j]=c[i-1][j-1]+1;
b[i][j]=1;
}
elseif(c[i-1][j]>=c[i][j-1])
{
c[i][j]=c[i-1][j];
b[i][j]=2;
}
else
{
c[i][j]=c[i][j-1];
b[i][j]=3;
}
}
cout<}
//根据b[i][j]的内容打印a,x数组的最长公共子序列
voidLCS(inti,intj,int*x,intb[][N]){
if(i==0||j==0)return;
if(b[i][j]==1)
{
LCS(i-1,j-1,x,b);
for(inty=1;y
if(x[y]==x[i])
return;
cout<}
elseif(b[i][j]==2)
{
LCS(i-1,j,x,b);
}
else
LCS(i,j-1,x,b);
}
voidQuickSort(inta[],intp,intr){
if(p{
intq=Partition(a,p,r);
QuickSort(a,p,q-1);//对左半段排序
QuickSort(a,q+1,r);//对右半段排序
}
}
intPartition(inta[],intp,intr){
inti=p,
j=r+1;
intx=a[p];
//将//将>x的元素交换到右边区域
while(true)
{
while(a[--j]>x);
while((iif(i>=j)break;
Swap(a[i],a[j]);
}
a[p]=a[j];
a[j]=x;
returnj;
}
voidSwap(int&x,int&y){
intt;
t=x;
x=y;
y=t;
}
voidmain(void)
{
int*a,*x;
a=newint[N];
x=newint[N];
intb[N][N];
intc[N][N];
cout<<"请输入十个数:
"<for(inti=1;i{
cin>>a[i];
x[i]=a[i];
}
QuickSort(x,1,N-1);
LCSL(N-1,N-1,a,x,c,b);
LCS(N-1,N-1,a,b);}