首页 > 代码库 > zoj 2527 - Series

zoj 2527 - Series

题目:计算最长的等差数列长度。

分析:dp,LIS类似物,二分。先排序,然后枚举前面的所有点作为前一个元素求公差即可。

            更新时,利用二分找到,距离当前位置最近的前第二元素,

            如果不存在,则直接更新为 2即可。 

说明:如果数据范围小的话,可在连续区间dp(O(L^2))。(2011-10-03 17:34)

#include <stdio.h>
#include <stdlib.h>

int D[ 1005 ];
int F[ 1005 ][ 1005 ];

int cmp( const void* a, const void* b )
{
    return *((int *)a) - *((int *)b);
}

int find( int h, int key )
{
    int m,l = 1;
    while ( l < h ) {
        m = (l+h)>>1;
        if ( D[ m ] <= key )
            l = m+1;
        else h = m;
    }
    return h;
}

int main()
{
    int n;
    while ( ~scanf("%d",&n) ) {
        for ( int i = 1 ; i <= n ; ++ i )
            scanf("%d",&D[ i ]);
        qsort( &D[ 1 ], n, sizeof( int ), cmp );
        for ( int i = 1 ; i <= n ; ++ i )
        for ( int j = 1 ; j <  i ; ++ j )
            F[ i ][ j ] = 1;
        
        for ( int i = 2 ; i <= n ; ++ i )
        for ( int j = 1 ; j <  i ; ++ j ) {
            int d = D[ i ]-D[ j ];
            int s = find( j, D[ j ]-d )-1;
            if ( s > 0 && D[ s ] == D[ j ]-d ) {
                if ( F[ i ][ j ] <= F[ j ][ s ] )
                    F[ i ][ j ] = F[ j ][ s ] + 1;
            }else if ( s <= 0 || F[ i ][ j ] < 2 )
                F[ i ][ j ] = 2;
        }
        
        int Min = 1;
        for ( int i = 1 ; i <= n ; ++ i )
        for ( int j = 1 ; j <  i ; ++ j )
            if ( Min < F[ i ][ j ] )
                Min = F[ i ][ j ];
        
        printf("%d\n",Min);
    }
    return 0;
}


zoj 2527 - Series