正文

Zoj 2527 Series2008-02-19 19:30:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/cruxd/32773.html

分享到:

2755219 2008-02-19 18:56:56 Accepted 2527 C++ 00:00.07 4364K C.D.

做了两天题后有点头昏脑胀,上星期连着熬夜看联盟杯的后遗症不失时机地蹦出来张牙舞爪。也罢,这个礼拜要好好休息,不看冠军杯了。 (其实上个赛季也都是看Bt录播,人懒没药医 =.= )

一道简单的DP。难点在于原来的算法时间复杂度O(N^3),N=1000。

题目描述相当简单,给定一个数组,求其中最长的等差数列的长度。

首先考虑一维规划。显然不行,一个等差数列不能用一个数字进行定义。转而考虑二维。当数列的差不大时,可以考虑用F(i,d)表示当前一个数a[i]下等差为d的数列长度。可是这个数列给出了1e10的范围……

继续转进。F(i,j)表示数列的最后一个数是a[i],倒数第二个是a[j]。这样就保存了等差,也可以求得倒数第三个数,前提是找得到。只要在数组里找到它的位置k,就可以继续方程式:F(i,j) = F(j,k) + 1。

但是这样一来无疑要遍历整个数组,使O上升到N^3,这太慢了。为此先对整个数组排序,去除重复的数字,然后在有序的数组里可以用二分搜索k。O(N^2*log(N)),完全满足时间要求。

#include <cstdio>
#include 
<string>
#include 
<cstdlib>

int b[1001][1001], a[1001], N, ans;

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


int init ();
int b_search ( intintint );
void dp ();

int main ()
{
    
//freopen ( "in.txt", "r", stdin );
    while ( init () )
    
{
        dp ();
        printf ( 
"%d\n", ans );
    }

    
return 0;
}


int init ()
{
    
if ( scanf ( "%d"&N ) == EOF )
    
{
        
return 0;
    }

    
int i;
    
for ( i = 0; i < N; i ++ )
    
{
        scanf ( 
"%d"&a[i] );
    }

    ans 
= 0;
    qsort ( a, N, 
sizeof ( a[0] ), cmp );
    
int pre = 1000000001, l = 0, t;
    
for ( i = 0; i < N; i ++ )
    
{
        
if ( a[i] != pre )
        
{
            a[l 
++= a[i];
            
if ( ans < t )
            
{
                ans 
= t;
            }

            t 
= 1;
        }

        
else
        
{
            t 
++;
        }

        pre 
= a[i];
    }

    
if ( ans < t )
    
{
        ans 
= t;
    }

    
return N = l;
}


void dp ()
{
    
int i, j;
    
for ( i = 0; i < N; i ++ )
    
{
        
for ( j = i - 1; j >= 0; j -- )
        
{
            
int l = 2 * a[j] - a[i];
            
int k = b_search ( l, 0, j - 1 );
            
if ( k == -1 )
            
{
                b[i][j] 
= 2;
            }

            
else
            
{
                b[i][j] 
= b[j][k] + 1;
            }

            
if ( ans < b[i][j] )
            
{
                ans 
= b[i][j];
            }

        }

    }

}


int b_search ( int x, int l, int r )
{
    
if ( x <a[l] || x> a[r] )
    
{
        
return -1;
    }

    
int m;
    
while ( l <= r )
    
{
        m 
= ( l + r ) >> 1;
        
if ( a[m] == x )
        
{
            
return m;
        }

        
if ( a[m] > x )
        
{
            r 
= m - 1;
        }

        
else
        
{
            l 
= m + 1;
        }

    }

    
return -1;
}

阅读(3373) | 评论(1)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

loading...
您需要登录后才能评论,请 登录 或者 注册