赞
踩
动态规划(dynamic programming)是运筹学的一个分支,是求解决策过程(decision process)最优化的数学方法。20世纪50年代初美国数学家R.E.Bellman等人在研究多阶段决策过程(multistep decision process)的优化问题时,提出了著名的最优化原理(principle of optimality),把多阶段过程转化为一系列单阶段问题,利用各阶段之间的关系,逐个求解,创立了解决这类过程优化问题的新方法——动态规划。
编号动态规划:最大不下降子序列
划分动态规划:矩阵链乘、凸多边形三角剖分
数轴动态规划:0-1背包
前缀动态规划:最长公共子序列
树形动态规划:最优二分搜索树
或者
线性动规:拦截导弹,合唱队形,挖地雷,建学校,剑客决斗等;
区域动规:石子合并, 加分二叉树,统计单词个数,炮兵布阵等;
树形动规:贪吃的九头龙,二分查找树,聚会的欢乐,数字三角形等;
背包问题:01背包问题,完全背包问题,分组背包问题,二维背包,装箱问题,挤牛奶等
或者
计数:如选出k个数使得和是sum
求最大最小值:最大上升子序列
求存在性:博弈
基本思想:问题的最优解如果可以由子问题的最优解推导得到,则可以先求解子问题的最优解,在构造原问题的最优解;若子问题有较多的重复出现,则可以自底向上从最终子问题向原问题逐步求解。
使用条件:可分为多个相关子问题,子问题的解被重复使用
动态规划算法的设计步骤:
分析优化解的结构
递归地定义最优解的代价
自底向上地计算优化解的代价保存之,并获取构造最优解的信息
根据构造最优解的信息构造优化解
动态规划特点:
把原始问题划分成一系列子问题;
求解每个子问题仅一次,并将其结果保存在一个表中,以后用到时直接存取,不重复计算,节省计算时间
自底向上地计算。
整体问题最优解取决于子问题的最优解(状态转移方程)(将子问题称为状态,最终状态的求解归结为其他状态的求解)
动态规划与分治法的区别:
动态规划算法与分治法类似,其基本思想也是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。与分治法不同的是,适合于用动态规划求解的问题,经分解得到子问题往往不是互相独立的。若用分治法来解这类问题,则分解得到的子问题数目太多,有些子问题被重复计算了很多次。
(1)确定状态
最后一步:
K枚银币面值总和是27
一定有最后的一枚硬币:a
前面总面额是27-a
(我们不关心前面有多少种拼法)
(27-a的硬币数量一定要最少)(最优策略)
子问题:
最少用多少枚硬币可以拼出27-a(规模更小)
如果a = 2, f(27) = f(27-2)+1
如果a = 5, f(27) = f(27-5)+1
如果a = 7, f(27) = f(27-7)+1
f(27) =min{f(25)+1,f(22)+1,f(20)+1}
(2)转移方程
f【27】 =min{f【25】+1,f【22】+1,f【20】+1}
(3)初始条件和边界情况
边界条件
Q1 x-2,x-5,x-7 小于0怎么办?
Q2 什么时候停下来?
Q3 拼不出来怎么办?
返回正无穷
初始条件 f[0]=0
(4)计算顺序;从小到大
算法复杂度O(n*m)
#include <stdio.h> #include <math.h> //Coin change //有银币面值2元,5元,7元无限,求最少的银币,刚好付清,如输入27,输出5 #define max 10000 int min(int x,int y){ if(x>y) return y; else return x; } int coinChange(int v[],int M){ int f[M+1]; f[0]=0; for(int i = 1;i<= M;i++){ f[i] = max; for(int j = 0;j<3;j++){ if(i>=v[j]&&f[i-v[j]]!=max){ f[i]= min(f[i-v[j]]+1,f[i]); } } } if(f[M]==max){ return -1; } return f[M]; } int main(){ int m; int v[3] = {2,5,7}; scanf("%d",&m); printf("%d",coinChange(v,m)); return 0; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。