理解树上的dp

时间:2018-03-31 06:26:16

标签: c++ algorithm matrix dynamic-programming

我最近解决了Codeforces的问题。在给出了很多尝试后,我无法得到树dp中的矩阵计算如何在编辑解决方案中起作用。以下是我在其中不理解的部分添加注释的代码。

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int f[2][10010][110];//0 max 1 min
char s[10010];
int tr[10010][2],size,n,fa[10010],p,m,minn,pre;
void dfs(int x)
{
    //cout<<x<<" "<<f[0][x][0]<<endl;
    if (!tr[x][0]) return;
    int l=tr[x][0],r=tr[x][1];
    dfs(l),dfs(r);

    /*The part which gets complicated  need help why and how this calculation works*/
    for (int i=0;i<=minn;i++)
        for (int j=0;i+j<=minn;j++)
        {
            f[0][x][i+j+(p<m)]=max(f[0][x][i+j+(p<m)],f[0][l][i]+f[0][r][j]);
            f[0][x][i+j+(p>=m)]=max(f[0][x][i+j+(p>=m)],f[0][l][i]-f[1][r][j]);
            f[1][x][i+j+(p<m)]=min(f[1][x][i+j+(p<m)],f[1][l][i]+f[1][r][j]);
            f[1][x][i+j+(p>=m)]=min(f[1][x][i+j+(p>=m)],f[1][l][i]-f[0][r][j]);
        }
}
int main()
{
    scanf("%s",s+1);
    scanf("%d%d",&p,&m);
    memset(f[0],-63,sizeof(f[0]));
    memset(f[1],63,sizeof(f[1]));
    /* Why we have used min of the two and how does it handle both condition */
    minn=min(p,m);
    n=strlen(s+1);
    size=1;pre=size;
    for (int i=1;i<=n;i++)
    {
        if (s[i]=='('||s[i]=='?')
        {
            tr[pre][tr[pre][0]?1:0]=++size;
            fa[size]=pre;
            pre=size;
        }
        else if (s[i]==')') pre=fa[pre];
        else f[0][size][0]=f[1][size][0]=s[i]-'0',pre=fa[pre];
    }
    dfs(1);
    printf("%d",f[0][1][minn]);
} 

我迷失的部分是这个

f[0][x][i+j+(p<m)]=max(f[0][x][i+j+(p<m)],f[0][l][i]+f[0][r][j]);
f[0][x][i+j+(p>=m)]=max(f[0][x][i+j+(p>=m)],f[0][l][i]-f[1][r][j]);
f[1][x][i+j+(p<m)]=min(f[1][x][i+j+(p<m)],f[1][l][i]+f[1][r][j]);
f[1][x][i+j+(p>=m)]=min(f[1][x][i+j+(p>=m)],f[1][l][i]-f[0][r][j]);

我总是在努力解决这类问题。有人可以提供解决此类问题的链接。

1 个答案:

答案 0 :(得分:0)

你不了解哪部分线路?我走了一行

f[0][x][i+j+(p<m)]=max(f[0][x][i+j+(p<m)],f[0][l][i]+f[0][r][j]);

并重写

const int index_max = 0;
int y = i+j + (p<m? 1: 0); // in your code p<m is cast to int, true=1, false=0
int old_max = f[index_max][x][y];
int next_value = f[index_max][l][i] + f[index_max][r][j]:
f[index_max][x][y] = max(old_max, next_value);

您正在寻找双循环next_value的最大值。由于lr是固定的,next_value s是两行中值的总和。

与其他3行类似。