博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
『最长等差数列 线性DP』
阅读量:7094 次
发布时间:2019-06-28

本文共 1478 字,大约阅读时间需要 4 分钟。


最长等差数列(51nod 1055)

Description

N个不同的正整数,找出由这些数组成的最长的等差数列。

例如:1 3 5 6 8 9 10 12 13 14
等差子数列包括(仅包括两项的不列举)
1 3 5
1 5 9 13
3 6 9 12
3 8 13
5 9 13
6 8 10 12 14
其中6 8 10 12 14最长,长度为5。

Input Format

第1行:N,N为正整数的数量(3 <= N <= 10000)。 第2 - N+1行:N个正整数。(2<= A[i] <= 10^9)

Output Format

最长等差数列的长度。

Sample Input

10 1 3 5 6 8 9 10 12 13 14

Sample Output

5

解析

对于一个序列的特定最优值求解,应该很容易想到是线性DP。第一步首先排序是很容易想到的。

第一个突破口在状态的设置,如果直接用n设置状态,发现会很难处理转移的问题。

\(f[i][j]\)代表以\(a_i\)为第一项,\(a_j\)为第二项所构成的等差数列的最长长度\((i<j)\)

考虑若\(a_k\)可以作为这个等差数列的第三项,且满足\((i<j<k)\),那么\(f[i][j]=f[j][k]+1\)

由等差数列的性质可以得知,当\(a_k\)可以作为第三项时:\(a_j*2=a_i+a_k\)
此时我们枚举\(j\),将\(i\)\(k\)设为指针利用性质的大小关系去扫描即可,可以做到时间复杂度\(O(n^2)\)
当然,由于\((i<j<k)\),所以转移时需要倒序枚举。

\(Code:\)

#include
using namespace std;inline void read(int &k){ int w=0,x=0;char ch; while(!isdigit(ch))w|=ch=='-',ch=getchar(); while(isdigit(ch))x=(x<<3)+(x<<1)+(ch^48),ch=getchar(); k=(w?-x:x);return;}const int N=10000+80;int n,a[N];short int f[N][N]={},ans=2;inline void input(void){ read(n); for(int i=1;i<=n;i++)read(a[i]);}inline void init(void){ sort(a+1,a+n+1); for(int i=1;i
=2;j--) { int i=j-1,k=j+1; while(i>=1&&k<=n) { if(a[j]*2==a[i]+a[k]) { f[i][j]=f[j][k]+1; ans=max(ans,f[i][j]); k++,i--; } if(a[j]*2>a[i]+a[k])k++; if(a[j]*2

考点:灵活的状态设置。


转载于:https://www.cnblogs.com/Parsnip/p/10210595.html

你可能感兴趣的文章
PAT天梯赛L3-007 天梯地图
查看>>
两年之中
查看>>
【翻译】使用Visual Studio在Azure上部署Asp.Net Core Web应用
查看>>
Switch Game
查看>>
整数A和B的二进制表示有多少位不同
查看>>
获取后台数据显示在网页(一)
查看>>
POJ-2349 Arctic Network---MST的第m长的边
查看>>
【Unity3D入门教程】游戏开发利器UGUI的基本使用方法
查看>>
wordpress博客服务器迁移过程中总结
查看>>
leetcode 83. Remove Duplicates from Sorted List
查看>>
利用JS实现闪烁字体
查看>>
【原创】菜鸟版Android 笔记2- Activity
查看>>
使用JAVA反射初始化数组(转)
查看>>
IIS7.5解决应用程序池回收假死问题
查看>>
如何配置oracle数据库的连接
查看>>
[BJOI2019]排兵布阵——分组背包
查看>>
Python之List列表的增删改查
查看>>
DataTrigger 绑定枚举
查看>>
单节点GI(ASM)+DB 安装以及它对oracle DB自动重启的守护(11g)
查看>>
数池塘
查看>>