数字三角形动态规划算法 c语言,动态规划算法:数字三角形问题

问题描述:

有一个有非负整数组成的三角形,第一行只有一个数,除了最下行之外的每个数的左下方和右下方各有一个数。如下图:

1295903506955313152.htm

从第一行的数字开始每次可以向左走或者向右走,直到走到最下行,把沿途经过的所有数字全部加起来,如何走才能使这个和最大?

1.        回溯法:可以求出所有的路线,然后从所有的路线中选择最好的,但是效率太低。

2.        动态规划:

1)        把当前的位置(i,j)看成一个状态,定义状态(i,j)的指标函数d(i,j)为从(i,j)出发时能得到的最大和(包括(i,j)本身的值)。原问题的解是:d(1,1)。

2)        状态转移:d(i,j)=a(i,j)+max{d(i+1,j),d(i+1,j+1)}.

3)        递归程序实现:程序简洁,但是效率低,因为存在大量重复计算的节点。

int solve(int i,int j)

{

return a[i][j]+(i==n? 0 : max(solve(i+1,j),solve(i+1,j+1)));

}

4)        递推程序实现:时间复杂度为O(n^2),最下面一行单独处理后,从下至上逆序枚举每一行。

int i,j;

for(j=1;j<=n;j++)

{

d[n][j]=a[n][j];

}

for(i=n-1;i>=1;i--)

{

for(j=1;j<=i;j++)

{

d[i][j]=a[i][j]+max(d[i+1][j],d[i+1][j+1]);//d[i+1][j],d[i+1][j+1]已经先于d[i][j]计算出

}

}

5)        记忆化搜索:不必事先确定各状态的计算顺序,但需要记录每个状态“是否计算过”。

memset(d,-1,sizeof(d));

int solve(int i,int j)

{

if(d[i][j]>=0)

{

return d[i][j];

}

return d[i][j]=a[i][j]+(i==n ? 0 : max(solve(i+1,j), solve(i+1,j+1)) );

}

程序依然是递归的,但是能避免重复访问节点。因为所有的数字非负,那么已经算出的结点就应该是非负的,首先清空状态函数为-1,若不小于0,那么不用再计算。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值