我最近解决了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]);
我总是在努力解决这类问题。有人可以提供解决此类问题的链接。
答案 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
的最大值。由于l
,r
是固定的,next_value
s是两行中值的总和。
与其他3行类似。