【问题标题】:Understanding the dp on tree了解树上的 dp
【发布时间】:2023-03-17 04:25:01
【问题描述】:

我最近解决了来自Codeforces 的一个问题。在进行了很多尝试之后,我无法在 tree dp 中了解矩阵计算在编辑解决方案中的工作原理。以下是我在其中不明白的部分添加了 cmets 的代码。

#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]);

我总是与这类问题作斗争。有人可以提供解决此类问题的链接吗?

【问题讨论】:

    标签: c++ algorithm matrix dynamic-programming


    【解决方案1】:

    你不明白这句话的哪一部分?我用一行

    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_values 的最大值。由于lr 是固定的,next_values 是两行中值的总和。

    其他 3 行类似。

    【讨论】:

    • 不,这不是代码的编写方式,实际上我们为什么要这样做。我的意思是它的逻辑部分。如果你能告诉我会很高兴。
    猜你喜欢
    • 1970-01-01
    • 2013-12-25
    • 1970-01-01
    • 2013-04-10
    • 1970-01-01
    • 2014-07-04
    • 2014-12-21
    • 1970-01-01
    • 2013-12-29
    相关资源
    最近更新 更多