动态规划笔记

动态规划笔记

由于自己是非计算机专业,而对编程学习比较感兴趣,特学习算法导论一书,根据书上伪代码来练习,一来提高自己算法思维,二来督促自己好好学习,不能虚度光阴。

一:思想

  动态规划,通常用来求解最优化问题,这类问题有很多可行解,我们希望寻找其最优解,通常是最大值最小值。
  具体步骤就是一个大问题可以分为很多子问题,通过求解小规模的子问题,进而组合子问题得到原问题的解。使用动态规划解决问题,需要具备以下两个因素。

  • 最优子结构:一个问题的最优解包含子问题的最优解。也就是一个最优解,它也必须是字问题的最优解。
  • 重叠子问题:问题的递归算法要重复求解相同的子问题,而不是一直生成新问题。

二:例题

1 钢条切割问题

对于长度为 i 的钢条的价格 pi 如下。如何切割达到价值最大。

这里写图片描述

  • 最优子结构:当钢条完成首次切割后,变成两段独立的钢条。进而求解两段独立的钢条最优解,然后相加即可。
  • 重叠子问题:钢条越切越少,则子问题重叠的越多。
    我们将钢条从左边切下的长度记为i的那一段,只对右边长度n-i的一段继续进行切割(递归求解),对左边的不再进行切割。即问题转化为:第一段长度求解如下最大值:
    rn=max(pi+pni),i=1...n
    .

自顶向下法自然求解
所谓自顶向下法,是直接利用递归的算法求解原问题。再次期间递归调用会继而求解小规模问题。
这里写图片描述

此算法可以改进,因此它会多次重复的计算规模更小的子问题。解法方法是引入备忘录机制,当 i<n 时,最大收益被计算 ri ,就保存起来,下次计算到的时候,直接查表引用,不必再进行递归计算。

//直接递归计算
//int cut_rod(int p[],int n)
//{
//  if(n==0)
//      return 0;
//  int q=-1;
//  for(int i=1;i<=n;i++)
//  {
//      int temp=p[i]+cut_rod(p,n-i);
//      if(q<temp)
//      {
//          q=temp;
//      }
//  }
//  return q;
//}

//带备忘录:先定义一个数组存放计算过的收益,此数组不能放到递归里。
//int  Memoized_cut_Rod(int p[],int n)
//{
//  vector<int>r(n,-1);
//  return Memoized_cut_Rod_Aux(p,n,r);
//}
//int Memoized_cut_Rod_Aux(int p[],int n,vector<int>r)
//{
//  int q=-1;
//  if(r[n]>=0)
//      return r[n];
//  if(n==0)
//      q=0;
//  else
//  {
//      for(int i=1;i<=n;i++)
//      {
//          int temp=p[i]+Memoized_cut_Rod_Aux(p,n-i,r);
//          if(q<temp)
//          {
//              q=temp;
//          }
//      }
//      r[n]=q;
//  }
//  return q;
//
//}

自底向上法求解小规模问题
自底向上法是直接先求解小规模问题,在小规模问题上逐步求解大规模问题。

//int Bottom_up_cut_rod(int p[],int n)
//{
//  vector<int>r;//保存切割的最优值
//  vector<int>s;//保存切割点
//  r.push_back(0);
//  s.push_back(0);
//  for(int j=1;j<=n;j++)//逐步求解规模j的问题,一直求解到n,即原问题
//  {
//      int q=-1;
//      for(int i=1;i<=j;i++)
//      {
//          int temp=p[i]+r[j-i];
//          if(q<temp)
//          {
//              q=temp;
//              s.push_back(i);
//          }
//      }
//      r.push_back(q);
//  }
//  return r[n];
//}
//

实例计算

int main()
//{
//  int p[]={0,1,5,8,9,10,17,17,20,24,30};
//  cout<<cut_rod(p,5)<<endl;
//  cout<<Memoized_cut_Rod(p,5)<<endl;
//  cout<<Bottom_up_cut_rod(p,5)<<endl;
//  getchar();
//  
//}
2 矩阵链相乘问题

给定n个矩阵序列 <A1,...,An> <script type="math/tex" id="MathJax-Element-5"> </script>,如何加括号明确计算次序,进行更优的计算。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值