这是USACO的一道记忆化搜索题,还记得原来学搜索就是被此所困。
给定n深的数,第i层有i个节点,存储有一个数字,询问从第一层走到最后一层所经过节点上数字和的最大值。我们很容易想到枚举所有路径来计算最大值,但这是2^n的复杂度,显然,对于固定的x,y的返回值是一定的,与上面怎么走过来的没有关系,所以会造成重复统计,所以我们要想办法进行优化。发现每个点只于下面的左子树最大值与右子树最大值有关,所以我们要做的就是再开一个f[][]数组记忆每一个点的最大值,如果被标记为已经记忆,即f数据被修改了,那么直接返回即可;如果没有修改,那么则累加下面的最大值即可。
dfs代码
int dfs(int x,int y){ if(x==n) return mp[x][y]; else return mp[x][y]+max(dfs(x+1,y),dfs(x+1,y+1)) } int ans=dfs(1,1);
记忆化搜索代码
void dfs(int x,int y){ if(f[x][y]!=0) return f[x][y]; if(x==n) return mp[x][y]; else return f[x][y]=mp[x][y]+max(dfs(x+1,y),dfs(x+1,y+1)); }