• 『最长等差数列 线性DP』


    <更新提示>

    <第一次更新>


    <正文>

    最长等差数列(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<bits/stdc++.h>
    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<n;i++)
    		for(int j=i+1;j<=n;j++)
    			f[i][j]=2;
    }
    inline void dp(void)
    {
    	for(int j=n-1;j>=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<a[i]+a[k])i--;
    		} 
    	}
    }
    int main(void)
    {
    	input();
    	init();
    	dp();
    	printf("%d
    ",ans);
    	return 0; 
    } 
    

    考点:灵活的状态设置。


    <后记>

  • 相关阅读:
    06
    05
    继承
    0713作业
    0712作业
    0711作业
    福彩双色球作业
    0709作业
    选择语句+循环语句作业
    0706作业
  • 原文地址:https://www.cnblogs.com/Parsnip/p/10210595.html
Copyright © 2020-2023  润新知