题意
给你 n 个数,让你从中找出最长的等差序列
思路
dp求最长等差数列的长度
dp [ i ] [ j ] :以第 i 个数为倒数第二位,第 j 个数为倒数第一位的等差序列的长度;
转移方程 dp [ i ] [ j ] = dp [ k ] [ i ] + 1;
如果 n > = 2 , 那么等差序列最短长度也是 2 ,所以 dp 初始化可以初始化为 2 .
代码
#include<iostream>
#include<string>
#include<map>
#include<set>
//#include<unordered_map>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
#include<iomanip>
#include<cmath>
#include<fstream>
#define X first
#define Y second
#define best 131
#define INF 0x3f3f3f3f
#define P pair<int,int>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const double eps=1e-7;
const double pai=acos(-1.0);
const int N=2e4+10;
const int maxn=4e5+10;
const int mod=1e9+7;
//const int d[4][2]={0,1,1,0,-1,0,0,-1};
int dp[5010][5010];
int n,a[5010];
int main(){
//ios::sync_with_stdio(false);
scanf("%d",&n);
for(int i=0;i<n;i++) scanf("%d",&a[i]);
sort(a,a+n);
for(int i=0;i<n-1;i++)
{
for(int j=i+1;j<n;j++)
{
dp[i][j]=2;
}
}
int maxx=2;
for(int i=1;i<n-1;i++)
{
int j=i+1,k=i-1;//这里是优化了一下(如果不优化会 T ,原来是三层循环)
//因为 k < i < j ,我们可以直接让j从i+1递增,k从i-1递减,这样就变成了两层,时间复杂度大大降低
while(k>=0&&j<n)
{
if(a[j]-a[i]==a[i]-a[k])//差值相等,说明正好,更新 dp
{
dp[i][j]=dp[k][i]+1;
if(dp[i][j]>maxx) maxx=dp[i][j];
k--,j++;
}
else if(a[j]-a[i]<a[i]-a[k]) j++;
else k--;
//差值不相等,往小的方向移动,因为移动后小的差值才会变大
}
}
printf("%d",maxx);
return 0;
}