重复口胡的动态规划

   今天老师口胡了一波动归,如果有其他人发了一篇差不多的,一定是我同学!

动态规划:

范围:适于解决多阶段、多决策、最优解(求方法数)问题

与贪心、分治的对比:

 贪心 :

   当前阶段 ,选最优(每次选取能取到的最优值,从而得到一个局部最优值) 。例题:潜水

 分治:   

      分而治之  ,也就是分->治
      例题(或用法):快排 ,归并排序

 动态规划:  

     当前阶段, 记录 所有的最优  (也就是常说的空间换时间)

     由于分部分的时候,重合部分经常出现,就会出现大量重复的递归调用,然而用了记忆化搜索来解决,可使动归 进一步 转换为递推。

   动态规划的两个必要条件:

  1)无后效性:当前的最优解与后面无关;
  2)最优子结构:每次都要保证最有值;

  看到这两个条件满足就基本确定是动态规划了;

  动归解题步骤:

  1)确定能用动态规划解决;
  2)划分阶段:时间,空间,顺序;(不同阶段效率不同,具体题目具体分析)
     拓扑排序*也是阶段划分
     floyd 的k循环
  3)设置状态:前i阶段的xxxxxx的最优值是什么
     设置f[i]([j]),表示某个状态的最优值
     洛谷 2519,为海亮题库(HLOJ)407加强版;
     状态是几维,循环也就是几重循环
   
     区间类:从第i个到第j个的最优值;
   
4)建立状态转移方程
   当前的状态(最优值、方案数)有前面那些状态推导出;
   继续加循环;
   
  例:零一背包:

    f[i][j]状态表示 前i个物品占据容量为j的背包的最优值
    故转移方程为
     f[i][j]=max(f[i-1][j](0,即不取),f[i-1][j-w[i]]+v[i](1,表示取));

*拓扑排序定义:拓扑排序顺序就是在图上做动态规划的阶段划分;(满足条件时)

动态规划的分类:

   动态规划分类的最终目的,是不分类。
 
1)  资源分配
   HLOJ411机械分配: f[i][j]   状态表示前i个公司 分配 j 台机器
           412马棚:状态:前i匹马分j个马棚
   使用三重循环实现;
   延伸:输出方案,是noip里也会考察的
2)  背包
   a ) 0/1  背包:
   f[i][j]=  max(f[i-1][j],f[i-1][j-c[i]]+w[i])
                     不要         要第i个物品
    用一维实现状态 :  f[j]   i循环(v...c[i]) 倒着循环;

PS:零一背包是其他所有背包类问题及变形的基础,所以一定要掌握,详见背包九讲(https://wenku.baidu.com/view/5e9062717fd5360cba1adb37.html)
  b)完全背包
   f[i][j]=  max(f[i-1][j],f[i][j-c[i]]+w[i])
                     不要         要第i个物品  
                     
        一维状态 :  f[j]   i循环(c[i]...v) 正着循环;    
    

PS:观察零一背包与完全背包二维状态、一维状态的分别不同之处并思考原因。
  c)多重背包
    每个物品有多个,第i个物品有k个,  1倍,2倍,3倍……k倍
      二进制优化  Log2(k)
    13= 1   12
        2   10
        4   6
        6
  d)二维体积背包
       f[i][j][k]设置三维的状态,其实与零一没什么区别,只要再加上一层循环而已,转移方程也类似

       同时也可以压缩为二维的:

       f[j][k]=max(f[j][k],f[j-w1[i]][k-w2[i]]+v[i]);

  e)分组:

       可以将每组都合并成一个物品,再按照零一来做;
      
  f)有依赖 (树形动态规划):

      这个。。。已经不在今天的范围之内了。。。

      若是想学习还是另请高明吧。

PS:背包类问题是动态规划的重点考点,熟悉掌握才能应对考场上的各种变形、结合的背包问题。
 

3)  双进程:

     两个进程,用i、j分别指示;通过两个进程之间的关系来求解;

     具体的可以自行百度;

     例题:最长公共子序列、构建双塔等;
       
4)  区间类  
    区间问题的状态设置、转移方程都不同于其他的dp,

    f[i][j]表示从第i个 到 第 j个 的最优值 

    f[i][j];
    阶段 : 区间长度
    for (int p=0;p<=n;p++) //区间长度
      for (int i=1;i<=n;i++)//起点位置
      {
         int j=i+p;//终点
         if (j>n)  break;//还可以这样。。。。
         求 f[i][j]
         
      }
    环状的区间类: 长度变两倍,依次去做
    
5) 二维  由线性变成了平面
    呵呵,我还没学呢;

    例题:农田个数、创意吃鱼;

    听说都是有意思的题;

----------------------------------------------------------------------------------------------------------------------------

   呼,就是这样,刘老师口胡一波的东西我加了一些改动就放上来了。。。。

猜你喜欢

转载自blog.csdn.net/qq_40900472/article/details/81806708