算法-动态规划(二)

栏目: 编程工具 · 发布时间: 5年前

导语

  • 还是没有整理完二叉树部分,用c一时,重构一世…树的独立集合,放在数据结构部分再搞了.
  • 下一篇是贪心法和拟阵

动态规划

概述

  • 动态规划简述是 把原问题分解为相对简单的子问题,再依次求解最终解决原问题的方法。
  • 许多子问题非常相似,动态规划中某个给定子问题的解已经得出,则存储,以便下次需要同一个子问题解之时直接查表。所以动态规划在输入的规模呈指数增长时特别有用。
  • 一个问题是否适用于动态规划求解,取决于 重叠子问题 最优子结构 和 无后效性

    • 最优子结构性质: 问题的最优解所包含的子问题的解也是最优的,可以通过求解子问题的最优解,来求解原问题.
    • 重叠子问题: 在自顶向下对问题进行求解时,每次产生的子问题并不总是新问题,有些子问题会被重复计算多次。动态规划通过保存已求解的子问题答案,避免冗余计算.
    • 无后效性: 子问题的解一旦确定,就不再改变,不受在这之后、包含它的更大的问题的求解决策影响。
  • 动态规划基本求解步骤

    • 分析优化解结构
    • 递归定义最优解代价
    • 自底向上计算最优解代价并保存子问题最优解
    • 根据最优解信息,构造优化解

randoms类

  • 提供原始数据,随机生成int , str 等.
  • 计算函数运行时间.
  • 代码

    class randoms(object):
      @classmethod
      def matrix(self, size=10, limt=10):
          matrix = [[random.randint(0, limt) for i in range(size)]
                    for j in range(size)]
          return matrix
    
  • 在原有 randoms 类中添加无负权的有向图生成.(当然这样每个结点都相连..)

树型动态规划

  • 输入是树,子问题是子树,复杂性是子树的个数.

最优二叉搜索树

  • 与划分动态规划类似.

  • 问题定义

    • 二叉搜索树(BST):

      • 算法-动态规划(二)
      • 结点
        • $K={k_1,k_2,…,k_n}$
        • $D={d_0,d_1,…,d_n}$
        • $d_i$对应区间$(k_i,k_{i+1})$,$d_0$对应$(-\infty,k_1)$,$d_n$对应$(k_n,+\infty)$.
      • 搜索概率
        • 搜索到$k_i$的概率为$p_i$
        • 搜索到$d_i$的概率为$q_i$
        • $\sum_{i=1}^{n}{p_i}+\sum_{j=0}^{n}{q_j}=1$
      • 搜索期望

    • 构建最优二叉搜索树(Optimal BST),即对于相同的搜索概率下,构建搜索期望最小的二叉搜索树
    • input: $K={k_1,k_2,…,K_n},k_1<k_2<…<k_n$, $k_i$概率对应$P={p_1,p_2,..,p_n}$. $d_i$的概率对应$Q={q_0,p_1,..,q_n}$.
    • output: K的最优二叉搜索树,$E(T)$最小.
  • 分析

    • 优化子结构
      • 如果最优二叉搜索树$T$有一子树 $T’$ ,包含关键词 ${k_i,k_{i+1},..,k_j}$ ,则 $T’$ 是集合 ${k_i,k_{i+1},..,k_j}$ 的最优搜索二叉树.
      • 证明: 假设 $T’$ 不是集合 ${k_i,k_{i+1},..,k_j}$ 的最优搜索二叉树.则存在 $T’’$ 为集合 ${k_i,k_{i+1},..,k_j}$ 的最优搜索二叉树, $T’’$ 替换 $T’$ 在 $T$ 的位置,得到了比 $T$ 更优的解,与前提矛盾.
      • 在输入的 $K={k_1,k_2,…,K_n},k_1<k_2<…<k_n$ 中,一定存在一个 $k_r$ 作为OBST的根节点.因为无法事前知道 $k_r$ .只能从 $k_1,..,k_n$ 遍历.
    • 重叠子问题
      • 如优化子结构分析.
      • 在输入为 $K1={k_1,k_2,…,k_{n-1}}$ 与 $K2={k_1,k_2,…,k_n}$ 时,子问题求解 $k_r$ ,所需要的子问题的解基本相同.
    • 最优二叉搜索树可以使用动态规划求解.
  • 其他

    • $matrix[i,j]$ 为 ${k_i,…,k_j}$ 的最优二叉搜索树的搜索期望.
    • 当 $j=i-1$ ,集合中只有叶节点 $d_{i-1}$ , $matrix[i,i-1]=q_{i-1}$
    • 当 $j>i-1$ ,集合中存在可以选定为 $k_r$ 的根节点,此时假定我们选择的是 $k_r$.其 $matrix[i,j]$ 可以表示为 $matrix[i,j] = matrix[i,r-1] + p_r + matrix[r+1,j] + w(i,r-1) + w(r+1,j)$
      • $w(i,r-1)$ 为集合${k_i,…,k_{r-1}}$选定为左子树,全部深度+1,后的最优二叉搜索树的搜索期望与 $matrix[i,r-1]$ 的差值.
      • 则 $w(i,r-1) = \sum_{l=i}^{r-1}{p_l}+\sum_{j=i-1}^{r-1}{q_j}$,可以合并 $matrix[i,j]$ 表达式中的 $w(i,r-1),w(r+1,j)$ 为 $w(i,j)$ ,且 $w(i,j) = \sum_{l=i}^{j}{p_l}+\sum_{s=i-1}^{j}{q_s} - p_r - q_r$
      • 因为并不知道 $k_r$ 具体取值,只能遍历所有可能取值.
  • 代码

    class bst(object):
      # p[0]为无效位
      def list_pq(self, size=10):
          tmp = randoms.list_int(size)
          tmq = randoms.list_int(size + 1)
          sums = sum(tmp) + sum(tmq)
          p = [x / sums for x in tmp]
          p.insert(0, 0)
          q = [x / sums for x in tmq]
          return [p, q]
    
      def w(self, k, i, j, p, q):
          return sum(p[i:j + 1]) + sum(q[i - 1:j + 1]) - q[k]
    
      def qbst(self, p, q):
          size = len(q)  # 0~n n+1个
          matrix = [[0 for i in range(size)] for j in range(size + 1)]
    
          for i in range(0, size):  # 填充第0斜线
              matrix[i + 1][i] = q[i]
          for i in range(1, size):  # 填充1~n斜线
              m = 1
              n = i
              while m < size and n < size:
                  matrix[m][n] = min([
                      matrix[m][k - 1] + matrix[k + 1][n] + self.w(
                          k, m, n, p, q) for k in range(m, n + 1)
                  ])
                  m += 1
                  n += 1
          return matrix[1][size - 1]
    
    
    if __name__ == "__main__":
      test = bst()
      arr = test.list_pq()
      p = arr[0]
      q = arr[1]
      tmp = test.qbst(p, q)
      print(tmp)
    
  • 这里仅输出了QBST的搜索期望,还需要一个与 matrix 同等规模的矩阵 root 记录每次选择的结果,根据 root 矩阵输出对应的二叉树.

  • w 函数部分,也可以应用动态规划求解,使用第三个与 matrix 同等规模的矩阵 w,防止重复计算.

树的独立集合

  • 二叉树部分代码还在转置python中.延后.

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

虚拟经济学

虚拟经济学

威利•莱顿维塔、爱德华•卡斯特罗诺瓦 / 崔毅 / 中国人民大学出版社 / 2015-6 / 49.00元

电子游戏中也存在 “看不见的手”吗?玩虚拟游戏能够创造真实价值吗?为什么现实世界需要虚拟经济?经济学作为一门成熟的学科,起源于对农业、制造业和商业的探究,曾经作为解决饥饿、就业这些人类所面对的真实问题的方法。然而,在虚拟世界,最为稀缺的资源不再是食物和住所,而是人类的关注度。一些基于农业、制造业和商业存在的经济学理论、概念依然适用于游戏中的虚拟世界,比如最为人们所熟知的“看不见的手”这一概念。同时......一起来看看 《虚拟经济学》 这本书的介绍吧!

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具