算法第九周

目录

一.分治法和动态规划的关系总结

二.备忘录方法

三.数字三角形路径问题


一.分治法和动态规划的关系总结

分治算法

动态规划算法

备忘录算法

相同点

分解原问题

分解原问题

构造递归方程

构造递归方程

不同点

自顶向下递归

自底向上递推

自顶向下递归

子问题相互独立

子问题重叠

子问题重叠

程序结构简单

保存已解决的子问题

保存已解决的子问题

时间复杂度高

时间复杂度低

时间复杂度低

二.备忘录方法

1.是动态规划的变形

2.用一个表保存已解决的子问题容案、再遇到子间题时,只要查看该子题的解,而不必重新求解。

  3.控制结构与动态规划算法不同,备忘录使用自顶向下的递归方式与直接递归方法相同。

4.计算思路

(1)为每个子问题建立一个记录项

(2)初始化时,记录存入一个特殊的值,表示该问题尚未求解。

(3)在求解时,对碰到的每个子问题先查看其相应的记录项,若是特殊值表示还未求 解过,需要求解并保存结果否则直接取出问题的解。

5.

相同点:都利用了子问题重叠性质,对每个子问题两种算法都只计算一次并记录答案,再碰到相同的问题是直接取用已得到的答案。

不同点:控制结构不同适用情况,当子问题空间中的部分子问题不必求解时,用备忘录方法效率较高,因为该方法只解决那些确实需要求解的子问题。

三.数字三角形路径问题

给定等腰直角数字三角形,请确定从顶至底的某个位置的一条路径,使该路径所经过的数字的总和最大。假设每一步可延直线向下或右斜线向下走。

使用备忘录方法解决数字三角形问题,求解最大数字和、以及其对应的路径。

#include<iostream>

#include<stdlib.h>

using namespace std;

const int m=5;

int v[m][m];

int M[m][m];

int lookuptriag(int i,int j){

int u1,u2;

if(M[i][j]>0)

return M[i][j];

if(i==0 && j==0){

return M[i][j]=v[i][j];

if(i==j){

cout<<i<<j<<M[i][j]<<endl;

M[i][j]=lookuptriag(i-1,j-1)+v[i][j];

return M[i][j];

}else{

if(i>j){

if(i!=0 && j==0){

M[i][j]=lookuptriag(i-1,j)+v[i][j];

cout<<i<<j<<M[i][j]<<endl;

}else{

u1=lookuptriag(i-1,j);

u2=lookuptriag(i,j-1);

M[i][j]=u1>u2?u1+v[i][j]:u2+v[i][j];

return M[i][j];

}

}

}

}

}

void TrackSolution(int i,int j){

printf("%d,%d\n",i,j);

while(i!=0 ||j!=0){

if(i==0){

j--;

printf("%d,%d\n",i,j);

}else{

if(j==0){

i--;

printf("%d,%d\n",i,j);

}else{

if(M[i-1][j]>=M[i][j-1]){

i--;

printf("%d,%d\n",i,j);

}else{

j--;

printf("%d,%d\n",i,j);

}

}

}

}

}

int main(){

int i,j,start,end,t,count;

printf("随机生成数字三角形如下:\n");

for(i=0;i<m;i++){

for(j=0;j<=i;j++){

v[i][j]=rand()%10;

M[i][j]=-1;

printf("%d\t",v[i][j]);

}

printf("\n");

}

count=lookuptriag(m-1,m-1);

printf("备忘录m三角形如下:\n");

for(i=0;i<m;i++){

for(j=0;j<=i;j++){

printf("%d\t",M[i][j]);

}

printf("\n");

}

printf("追总解如下\n");

TrackSolution(m-1,m-1);

return 1;

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值