BT based DP for max score

之前只做过一道基于BT的DP,还是瞿神一起讨论的,大学四年真的是代码写的太少。。。。

之前一道是计算BT里的最大pathsum, 任意起点终点,类似于记忆话存储,由于自己BT总是陷入指针,因此代码写的很繁琐,又是后续遍历推进,
又是层序遍历计算index,其实很多都可以缩减。

这道也是一样,https://vijos.org/p/1100
初看以为两边子树互相影响,然后不是DP,但是后来adhoc提示到左右子树都是连续的,因此可以DP,暂时不需要考虑树的样子。
DP方程 F(i,j)=max (F(i,k-1)*F(k+1,j)+A[k]) , i+1<=k<=j-1

只要重叠子问题首选DP,正如瞿神所说。后面再类似矩阵连s[i][j]记录断链位置,此处是根的位置,然后用递归构造先序遍历

#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
using namespace std;

typedef long long LL;

LL dp[30+1][30+1];
int s[30+1][30+1];
LL A[30+1];
vector<int> PreVec;
int n;
LL btmaxscore()
{
    //int length;
    for(int i=1;i<=n;i++)
        dp[i][i]=A[i],s[i][i]=i;
    //for(int i=1;i<=n-1;i++)
    //    dp[i][i+1]=1;
    for(LL length=2;length<=n;length++)
    {
        for(LL i=1;i<=n;i++)
        {
            LL j=i+length-1,max;
            max=1*dp[i+1][j]+A[i];s[i][j]=i;
            if(max<dp[i][j-1]*1+A[j])
                max=dp[i][j-1]*1+A[j],s[i][j]=j;
            for(LL k=i+1;k<=j-1;k++)
            {
                if(max<dp[i][k-1]*dp[k+1][j]+A[k])
                    max=dp[i][k-1]*dp[k+1][j]+A[k],s[i][j]=k;
            }
            dp[i][j]=max;
        }
    }
    /*
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            cout<<dp[i][j]<<" ";
        }
        cout<<endl;
    }*/
    return dp[1][n];
}
void PreOrder(int i, int j)
{
    if(i<=j)
    {
        PreVec.push_back(s[i][j]);
        PreOrder(i,s[i][j]-1);
        PreOrder(s[i][j]+1,j);
    }
}
int main()
{
    //freopen("in.txt","r",stdin);
    //int n;
    while(scanf("%d",&n)!=EOF)
    {
        for(int i=1;i<=n;i++)
            scanf("%I64d",&A[i]);
        LL maxscore=btmaxscore();
        PreVec.clear();
        PreOrder(1,n);

        printf("%I64d\n%d",maxscore,PreVec[0]);
        for(int i=1;i<PreVec.size();i++)
            printf(" %d",PreVec[i]);
        printf("\n");
    }
    return 0;
}

Posted by richard爱闹 - 8月 20 2014
如需转载,请注明: 本文来自 Richard