求数组的最长递增子序列VS吉哥系列故事——完美队形

来源:互联网 发布:淘宝店铺模块制作 编辑:程序博客网 时间:2024/05/19 01:31

题目链接:http://acm.hdu.edu.cn/diy/contest_showproblem.php?pid=1002&cid=18800&hide=0

腾讯2012.3.22的第三题就是基于求最长递增子序列的思想,不过是题目稍微变形了一下,求正串和反串中最大的公共递增子序列
首先给出求递增子序列的模板

#include<stdio.h>#define M 100000int a[M];int dp[M];int LIS(int nLen){//a是数据数组//dp是递推数组//nLen是数组a的长度int i,j;int nMax = 0;for(i = 0; i < nLen; ++i){dp[i] = 1;for(j = 0; j < i; ++j){if(a[i] > a[j])//如果是严格递增子序列则为>,非严格递增可取>={dp[i] = dp[i] > dp[j] + 1 ? dp[i] : dp[j] + 1;}}nMax = nMax > dp[i] ? nMax : dp[i];}return nMax;}void main(){int n;int i;int nMax;while(scanf("%d",&n) != EOF){for(i = 0; i < n; ++i){scanf("%d",&a[i]);}nMax = LIS(n);printf("%d\n",nMax);}}

比赛的时候想到了这个层面,但是当时觉得这个复杂度是o(n^2),所以想着怎么去优化,结果时间也过了,悲剧的没有提交,不说了,说多了全是泪啊。下面给出腾讯那道比赛题的参考代码,当然还是没有想出优化的算法。

#include<stdio.h>#include<string.h>#define M 210int a[M];int dp[M];int LIS(int nLen){//a是数据数组//dp是递推数组//nLen是数组a的长度int i,j;int mx;int ans = 0;for(i = nLen - 1; i >= 0; --i){mx = 0;for(j = 0; j <= i; ++j){if(a[j] < a[i])//dp[j]表示j之前的递增数对的数量{mx = mx > dp[j] ? mx : dp[j];}else if(a[j] == a[i]){dp[j] = mx + 1;//这里的加1,指的是数对的数量加1}if(j < i){ans = ans > dp[j] + dp[j] ? ans : dp[j] + dp[j];}else//如果j==i,在dp[j]=mx+1中就多加了1{ans = ans > dp[j] + dp[j] - 1 ? ans : dp[j] + dp[j] - 1;}}}return ans;}void main(){int n;int t;int i;int nMax;scanf("%d",&t);while(t--){scanf("%d",&n);memset(dp,0,sizeof(dp));for(i = 0; i < n; ++i){scanf("%d",&a[i]);}nMax = LIS(n);printf("%d\n",nMax);}}


原创粉丝点击