题目描述:
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。
输入
第1行:N,N为正整数的数量(3 <= N <= 10000)。
第2 - N+1行:N个正整数。(2<= A[i] <= 10^9)
输出
最长等差数列的长度。
输入样例
10
1
3
5
6
8
9
10
12
13
14
输出样例
5
分析:这是一道dp的题目。设dp[i][j]表示第一个数为a[i],第二个数为a[j],所构成的最长的等差数列长度。枚举k,如果a[k]可以作为等差数列的第三项,那么就一定满足a[j]*2=a[i]+a[k]。又发现这个东西具有单调性,所以我们只要倒的转移,用两个指针扫k的前面和后面,就行了
那么具体代码如下:
#include<bits/stdc++.h>
using namespace std;
#define GC getchar()
short int dp[10010][10010];//表示第一项为a[i],第二项为a[j]的最长
int a[100001];
short int maxx=0;
int n;
int main(){
scanf("%d",&n);
for (int i=1;i<=n;i++) scanf("%d",&a[i]);
// cout<<n<<' '<<a[1]<<' '<<a[2]<<endl;
// if (n==100) {cout<<30;return 0;}
sort(a+1,a+n+1);
for (int i=1;i<=n;i++)
for (int j=i+1;j<=n;j++)
dp[i][j]=2;
for (int j=n;j>=2;j--){
int i=j-1,k=j+1;
while (i>0&&k<=n){
if (a[i]+a[k]>a[j]*2) i--;
if (a[i]+a[k]<a[j]*2) k++;
if (a[i]+a[k]==a[j]*2) dp[i][j]=dp[j][k]+1,maxx=max(maxx,dp[i][j]),i--,k++;
}
}
// short int maxx=0;
for (int i=1;i<=n;i++)
for (int j=i+1;j<=n;j++)
maxx=max(maxx,dp[i][j]);
cout<<maxx;
return 0;
}