最长升序列求解(OJ 1093)

bupt acm oj: 1093

最长升序列 Submit: 1370   Accepted:446 Time Limit: 1000MS  Memory Limit: 65536KDescription
给出一个序列,求出此序列的最长升序列。
Input
第一行有一个正整数T(T < 10),表示测试数据的数量。
每组测试数据一行,先给出一个正整数n(n < 300),接下来是n个正整数组成的序列,求此序列的最长升序列。
Output
每组测试数据占一行,输出一个正整数s,表示最长升序列的长度
Sample Input
2
4 1 2 2 4
4 2 4 2 6
Sample Output
3
3

上面该题就是求解最长升序列,自己先做了一遍,是WA,还觉得是服务器判断错误,发现是自己读题错误。原来我在求解时候只要发现有元素大于之前的最大元素就加入到最长升序子序列,这样是不正确的,例如24346,最长升序应该是2346,而按照我的做法变成了246,少了。发现这个问题,没我想得那么简单,丢人啊~~

看了半天网上的算法,发现对动态规划算法算是看明白了。这里Mark一下。

f(i)表示L中以ai为末元素的最长递增子序列的长度。则有如下的递推方程:

  这个递推方程的意思是,在求以ai为末元素的最长递增子序列时,找到所有序号在L前面且小于ai的元素aj,即j<i且aj<ai。如果这样的元素存在,那么对所有aj,都有一个以aj为末元素

的最长递增子序列的长度f(j),把其中最大的f(j)选出来,那么f(i)就等于最大的f(j)加上1,即ai为末元素的最长递增子序列,等于以使f(j)最大的那个aj为末元素的递增子序列最末再加上ai;如果这样的元素不存在,那么ai自身构成一个长度为1的以ai为末元素的递增子序列。

#include<stdlib.h> #include<stdio.h> #define SIZE 300 int a[SIZE]; int b[SIZE]; int main() { int t; int n; scanf("%d",&t); if(t<0 || t>=10) return 0; for(int i=0;i<t;i++){ scanf("%d",&n); for(int j=0;j<n;j++) scanf("%d",&a[j]); b[0]=1; for(int i=1;i<n;i++){ b[i]=1; for(int j=0;j<i;j++) { if(a[j]<a[i] && b[j]+1>b[i]) b[i]=b[j]+1; } } int max=b[0]; for(int k=1;k<n;k++) if(max<b[k]) max=b[k]; printf("%d/n",max); } system("pause"); return 0; }

 if(a[j]<a[i] && b[j]+1>b[i]) b[i]=b[j]+1;//b[j]+1>b[i]保证了b[j]是i-1之前的最长升序长度

你可能感兴趣的:(最长升序列求解(OJ 1093))