最长单调子序列及计数(poj1952)
被这个问题困住了,就像憋了一泡屎,但是便秘了,不往下说了,你懂的。
在网上查了各种资料,各种文章,其实大家说的都差不多,无非是枚举、求该序列和它的排序后的序列的最大公共子序列、动态规划、基于〈二分法和统计研究〉论文。最基本最正常路子应该是动态规划,很多人会给出一个公式,然后给出一段代码,我看了很多,最终只看懂了一个。描述如下:
比如:另d[i]表示数列1到i, 以i结尾的最大长度值, 而令d[i] = max{ d[j]+1} (1<=j<=i-1 && a[j] > a[i])也就是说,对于每个可以接上的值, 都有a[j] > a[i](递减), 看谁能接的长, 自然就是最优解了。如果没有可接的, 就说明对于a[i]前边的没一个值, 都有a[j]>a[i], 也就是说a[i]是迄今位置最大的数了, 那么有d[i] = 1;
单看这个,想写出程序来也很难,所以,最好还是直接看程序。
对于poj上的1952题,难点其实是在计数上,m[i]用来存放计数,何时初始化计数?计数如何增加?如何防止重复?这是几个要考虑的问题,答案都在代码中了。
输入用例:
12
68 69 54 64 68 64 70 67 78 62 98 87
输出用例:
4 2 //最长是4;有2个长度为4的子序列
源程序:
1 #include <stdio.h> 2 int array[5000+1]; 3 int d[5000+1]; 4 int m[5000+1]; 5 int lds(int n) 6 { 7 int max; 8 int i, j; 9 for(i=n-1; i>=0; --i) 10 { 11 for(j=i+1; j<n; ++j) 12 { 13 if(array[i] > array[j]) 14 { 15 if(d[i] < d[j]+1) 16 { 17 d[i] = d[j]+1; 18 m[i] = m[j]; 19 } 20 else if(d[i] == d[j]+1) 21 { 22 m[i] += m[j]; 23 } 24 } 25 else if(array[i] == array[j]) 26 { 27 if(d[i] == 1) 28 { 29 m[i] = 0; 30 } 31 break;//防止重复 32 } 33 } 34 } 35 for(i=0, max=0; i<n; ++i) 36 { 37 if(max < d[i]) 38 { 39 max = d[i]; 40 } 41 } 42 int maxm; 43 for(i=0, maxm=0; i<n; ++i) 44 { 45 if(d[i] == max) 46 { 47 maxm += m[i]; 48 } 49 } 50 printf("%d %d\n", max, maxm); 51 return 0; 52 } 53 int main() 54 { 55 int i=0; 56 int nLastNum = -1; 57 int nArrayLen; 58 scanf("%d", &nArrayLen); 59 i=0; 60 while(i < nArrayLen) 61 { 62 scanf("%d", &array[i]); 63 m[i] = 1; 64 d[i] = 1; 65 ++i; 66 } 67 while(i<5001) 68 { 69 m[i] = 1; 70 d[i] = 1; 71 ++i; 72 } 73 lds(nArrayLen); 74 return 0; 75 }
posted on 2012-08-28 14:32 favourmeng 阅读(1087) 评论(0) 编辑 收藏 举报