牛客-Arithmetic Progressions(dp优化)

    科技2022-07-20  115

    题意

    给你 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; }
    Processed: 0.010, SQL: 8