最长不降子序列
小明晚上回家后,和爸爸玩这样的一个游戏:给出N个
(0<N<1000)整数,从左到右取数,除的第一个数以外,每取一个数都要不比前一个取的数小。谁能取最多的数谁就胜出,获得巧克力一块。
输入:N个整数。
输出:最多能取多少个数。
样例输入:
4 1 2 3 1 5 6
样例输出:
5
一、 动态规划算法:
本题是比较简单的动态规划,请理解好递推的过程。具体方法是对于数组a[],另设一数组b[],将b[]数组内元素全置1, 表示最短子序列长度为1。从数组a[]左到右一个个判断,每判断一个,则从这个元素向右寻找,找到比它小的元素,查看比它小的元素对应的b[]里存的长度 值。然后加上1。这样一步步的推完。数组b[]中间最大的即为所求最长子序列的长度。
状态转移方程:b[i]=max{b[j]} +1 , 0<=j<i。
#include<stdio.h>
#include<stdlib.h>
int
a[]={3,2,7,6,8,5,3,4,5,9,1,3};
int
b[]={1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
int main()
{
int
i,j,max;
for(i=0;i<12;i++)
{
max=0;
for(j=0;j<=i-1;j++)
{
if( a[i]>a[j] && max<b[j]+1 )
{
b[i]=b[j]+1;
max=b[i];
}
}
}
for(i=0;i<13;i++) printf("%d ",b[i]);
system("pause");
}
b[]数组中最大的即为所求长度。
-------------------------------------------------------------------------
方 法二:构造法
算法伪代码:
算法---求数组a[]的最长不减子序列长
{
置最长不减子序列长k为1;
用a[0]设置长为1的子序列的终止元素;
for(i=1;i<n;i++)
/*顺序至a[1]考察至a[n-1]*/
{
以子序列长为k至1的顺序寻找其终元素小于等于a[i]的长为j的子序列;
用a[i]作为长为j+1的子序列的终元素;
if(j==k)k++; /*最长不减子序列长k增1*/
}
}
例程:
#include<stdio.h>
int
a[6]={3,2,1,5,9,7};
int b[100]={0};
int main()
{
int
i,j,k;
k=1;
b[1]=a[0];
for(i=1;i<6;i++)
{
for(j=k;j>=1&&b[j]>a[i];j--);/*循环结束 ,J的指向*/
b[j+1]=a[i];
if(j==k)k++;
}
printf("k=%d",k);
system("pause");
}