动态规划 凑硬币

来源:互联网 发布:2017年99公益日数据 编辑:程序博客网 时间:2024/04/27 19:53

什么是动态规划?
  动态规划(Dynamic Programming,简称为DP)是运筹学的一个分支,是求解决策过程(decision process)最优化的数学方法。20世纪50年代初美国数学家R.E.Bellman等人在研究多阶段决策过程(multistep decision process)的优化问题时,提出了著名的最优化原理(principle of optimality),把多阶段过程转化为一系列单阶段问题,利用各阶段之间的关系,逐个求解,创立了解决这类过程优化问题的新方法——动态规划。1957年出版了他的名著《Dynamic Programming》,这是该领域的第一本著作。
  动态规划算法通常基于一个递推公式及一个或多个初始状态。当前子问题的最优解将由上一次子问题的最优解推出。使用动态规划来解题只需要多项式时间复杂度,因此它比回溯法、暴力法等要快许多。


问题:
如果我们有面值为1元、3元和5元的硬币若干枚,如何用最少的硬币凑够11元?

分析:
  用d(i)表示凑够i元需要的最少硬币数量,将它定义为该问题的”状态“。这个状态是怎么找出来的呢?根据子问题来定义状态,找到子问题,即 状态。最终要求解的问题,可以用这个状态来表示:d(11),即凑够11元最少需要多少个硬币。
  那状态转移方程是什么呢?既然我们用d(i)表示状态,那么状态转移方程自然包含d(i)。包含状态d(i)的方程,比如:d(3)=min{d(3-1)+1, d(3-3)+1}。没错,它就是状态转移方程,描述状态之间是如何转移的。当然,要对它抽象一下,d(i)=min{ d(i-Vj)+1 },其中i-Vj >=0,Vj表示第j个硬币的面值。有了状态和状态转移方程,这个问题基本上也就解决了。

求解:

int main()  {      int a[3] = {1,3,5}, sum = 11, dp[12];     dp[0] = 0;      for(int i = 1; i <= sum; i++) dp[i] = i; // 假设存在1元的硬币那么i元最多只需要i枚1元硬币,当然最好设置dp[i]等于无穷大      for(int i = 1; i <= sum; i++){          for(int j = 0; j < 3; j++){              if(i >= a[j] && dp[i - a[j]] + 1 < dp[i]){                  dp[i] = dp[i- a[j] ] + 1;              }          }      }      cout<<dp[sum]<<endl;      return 0;  }  

转自:http://blog.csdn.net/u013445530/article/details/45645307

原创粉丝点击