ZOJ:2672 Fibonacci Subsequence(动态规划+hash)

来源:互联网 发布:如何制作精美ppt 知乎 编辑:程序博客网 时间:2024/05/30 04:50

题意:在给定的数组里,寻找一个最长的序列,满足ai-2+ai-1=ai。并输出这个序列。

思路:

很容易想到一个DP方程

dp[i][j]=max(dp[k][i])+1. (a[k]+a[i]==a[j],1<=k&&k<i)

dp[i][j]表示序列最后两位是a[i],a[j]时的最长长度。

这个方程状态是O(n^2),转移是O(n),总复杂度是O(n^3)会超时。

进一步思考会发现转移这里是可以优化的。实际上我们只需要知道离i最近的那个满足a[k]+a[i]==a[j]的k就行,即最大k。

举个例子

2 3 -1 2 1 3

当i=5,j=6,即ai=1,aj=3时,这时需要找一个ak=2的,显然a1和a4满足,我们会选择a4而不是a1。因为可以转移到a1的状态一定都可以转移到a1,但能转移到a4的状态却不一定都能转移到a1,因此dp[4][5]>=dp[1][5]。这样我们只需要在遍历数组的时候维护数组每个数的最大的下标即可。这里使用hash来做。

注意卡内存,要用short。

#include<cstdio>#include<iostream>#include<cstdlib>#include<cstring>#include<hash_map>#include<ext/hash_map>using namespace std;int a[3001];short dp[3001][3001];struct Hash{    static const int mask = 0x7fff;    int p[32768], q[32768];    void clear()    {        for (int i = 0; i <= mask; ++i)            q[i] = -1;    }    int& operator[](int k)    {        int i = k & mask;        for (; q[i] != -1 && p[i] != k; i = (i + 1) & mask);        p[i] = k;        return q[i];    }} hash;int main(){    int n;    bool blank=false;    while(scanf("%d",&n)!=EOF)    {        if(blank) printf("\n");        else  blank=true;        memset(dp,0,sizeof(dp));        hash.clear();        for(int i=1; i<=n; ++i)        {            scanf("%d",&a[i]);            for(int j=i+1; j<=n; ++j)                dp[i][j]=1;        }        int ans=0,x=a[1],y;        for(int i=n; i>=1; --i)        {            for(int j=i-1; j>=1; --j)            {                int it=hash[a[i]+a[j]];                if(it!=-1)                {                    dp[j][i]=dp[i][it]+1;                }                if(ans<dp[j][i])                {                    ans=dp[j][i];                    x=a[j];                    y=a[i];                }            }            hash[a[i]]=i;        }        ans++;        printf("%d\n",ans);        printf("%d",x);        for(int i=2; i<=ans; ++i)        {            printf(" %d",y);            int t=y;            y=x+y;            x=t;        }        printf("\n");    }    return 0;}



0 0
原创粉丝点击