动态规划

动态规划思想?

解决多阶段决策问题常用的最优化理论
通过定义子问题,先求解子问题,然后在由子问题的解组合出原问题的解。把多阶段决策过程转化为一系列的单阶段决策问题
分治法的子问题之间是相互独立的(可能会有重复计算),而动态规划的子问题之间存在堆叠关系(递推关系式确定的递推关系)

动态规划的四个步骤?

解决多阶段决策最优化问题的一种思想,可以用带备忘录的穷举方法实现,也可以根据堆叠子问题之间的递推公式用递推的方法实现

  • 定义最优子问题(最优解的子结构)
    动态规划分解子问题不是简单地按照“大事化小”的方式进行的,而是沿着决策的阶段来划分子问题,决策的阶段可以随时间划分,也可以随着问题的演化状态来划分。
    0-1 背包问题:每选择装一个物品可以看做是一个阶段,其子问题就可以定义为每次向包中装(选择)一个物品
    最长公共子序列:按照问题的演化状态划分阶段,这就需要先定义状态,有了状态的定义,只要状态发生了变化,就可以认为是一个阶段
    装配线与工作站问题:按照时间或动作的顺序划分阶段
    凸多边形三角剖分问题:按照问题的组合状态划分阶段
  • 定义状态(最优解的值)
    状态的定义是建立在子问题定义基础之上的,因此状态必须满足无后向性要求。必要时,可以增加状态的维度,引入更多的约束条件,使得状态定义满足无后向性要求。
    0-1 背包问题:s[i,j] 定义为将第 i 件物品装入容量为 j 的背包中所能获得的最大价值(i,j为状态)
    最长公共子序列:s[i,j] 定义为 str1[1…i] 与 str2[1…j] 的最长公共子序列长度
  • 定义决策和状态转换方程(定义计算最优解的值的方法)
    决策就是能使状态发生转变的选择动作,如果选择动作有多个,则决策就是取其中能使得阶段结果最优的那一个。
    状态转换方程是描述状态转换关系的一系列等式,也就是从 n-1 阶段到 n 阶段演化的规律。状态转换取决于子问题的堆叠方式,如果状态定义得不合适,会导致子问题之间没有重叠,也就不存在状态转换关系了。没有状态转换关系,动态规划也就没有意义了,实际算法就退化为像分治法那样的朴素递归搜索算法了。
  • 确定边界条件
    对于递归加备忘录方式(记忆搜索)实现的动态规划方法,边界条件实际上就是递归终结条件,无需额外的计算。
    对于使用递推关系直接实现的动态规划方法,需要确定状态转换方程的递推式的初始条件或边界条件,否则无法开始递推计算。

归类

  • 线性模型
  • (字符或数字)串模型
  • 区间模型
  • 状态压缩模型

算法实现

1、01背包问题

import java.util.*;

public class test {
    public static int getMaxValue(int[] weight, int[] value, int w, int n) {
        int[][] table = new int[n + 1][w + 1];
        for (int i = 1; i <= n; i++) { //物品
            for (int j = 1; j <= w; j++) {  //背包大小
                if (weight[i] > j) {        
                    //当前物品i的重量比背包容量j大,装不下,肯定就是不装
                    table[i][j] = table[i - 1][j];
                } else {
                 	//装得下,Max(装物品i, 不装物品i)
                    table[i][j] = Math.max(table[i - 1][j], table[i - 1][j - weight[i]] + value[i]);
                }
            }
        }
        return table[n][w];
    }

    public static void main(String[] args) {
        int n = 5, w = 10;                    //物品个数,背包容量
        int[] value = {0, 6, 3, 5, 4, 6};     //各个物品的价值
        int[] weight = {0, 2, 2, 6, 5, 4};    //各个物品的重量
        System.out.println(getMaxValue(weight,value,w,n));
    }
}

2、最长公共子序列

int DpLcs(const std::string& str1, const std::string& str2, int s[MAX_STRING_LEN][MAX_STRING_LEN])
{
    std::string::size_type i,j;

    for(i = 1; i <= str1.length(); i++)
        s[i][0] = 0;
    for(j = 1; j <= str2.length(); j++)
        s[0][j] = 0;

    for(i = 1; i <= str1.length(); i++)
    {
        for(j = 1; j <= str2.length(); j++)
        {
            if((str1[i - 1] == str2[j - 1]))
            {
                s[i][j] = s[i - 1][j - 1] + 1; 
            }
            else
            {
                s[i][j] = std::max(s[i - 1][j], s[i][j - 1]); 
            }
        }
    }
    return s[str1.length()][str2.length()];
}

你可能感兴趣的:(架构,Java算法)