Dynamic programming : 分阶段求解决策问题 的的数学思想。也就是说将复杂的问题简化为简单的问题来处理。动态规划有三个重要的概念,最优子结构,边界,状态转移公式 。每个情况必须符合这三个条件方能求解。
Talk is cheap,Show me your code
话不多说,直接上题。
爬楼梯问题 有一座高度是10 级台阶的楼梯,从下往上走,每跨一步只能向上1 级或者2 级台阶。要求用程序来求出一共有多少种走法。
最优子结构 :F(10)=F(9)+F(8)
边界 :F(1)=1 F(2)=2 一个问题必须有一个边界,否则永远得不到有限的结果。
状态转移方程式 :F(n)=F(n-1)+F(n-2) 阶段与阶段之间的状态转移方程,这是动态规划的核心。决定了问题的每一个阶段和下一个阶段的关系。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 package mainimport "fmt" var step0 = 0 var step1 = 0 var step2 = 4 func main () { fmt.Println("递归DP:结果为" ,dp(10 ),"运行次数为:" ,step0) fmt.Println("递归DP:结果为" ,dp1(10 ),"运行次数为:" ,step1) fmt.Println("递归DP:结果为" ,dp2(10 ),"运行次数为:" ,step2) } func dp (height int ) (value int ){ if height>1 { step0++ return dp(height-1 )+dp(height-2 ) }else if height==2 { step0++ return 2 }else { step0++ return 1 } } func dp1 (height int ) (value int ){ stepList:=make ([]int ,10 ) stepList[0 ]=1 stepList[1 ]=2 var i int =2 step1+=4 for ; i<height; i++ { stepList[i]=stepList[i-1 ]+stepList[i-2 ] step1++ } return stepList[height-1 ] } func dp2 (height int ) (value int ) { var a = 1 var b = 2 var i =3 var temp int for ;i<=height;i++ { temp=a+b a=b b=temp step2++ } if a>b { return a } return b } 递归DP:结果为 89 运行次数为: 177 递归DP:结果为 89 运行次数为: 12 递归DP:结果为 89 运行次数为: 12
国王和金矿 有一个国家发现了5座金矿,每座金矿的黄金储量不同,需要参与挖掘的工人数也不同。参与挖矿工人的总数是10人。每座金矿要么全挖,要么不挖,不能派出一半人挖取一半金矿。要求用程序求解出,要想得到尽可能多的黄金,应该选择挖取哪几座金矿?
动态规划的问题都需要状态转移方程式 和边界值 。此题中设N为金矿数量,W是工人数量,G为金矿的数量,P为金矿的所需入手。
状态转移方程式 :F(N,W)=MAX( F(N-1,W) , F(N-1,W-P(i) + G(i) ) )
边界值 :F(n,w) = 0 (n<=1, w<p[0]);
F(n,w) = g[0] (n==1, w>=p[0]);
F(n,w) = F(n-1,w) (n>1, w<p[n-1])
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 package mainimport "fmt" var N = 5 var W = 10 var G []int = []int {500 ,200 ,300 ,350 ,400 } var P []int = []int {5 ,3 ,4 ,3 ,5 } func main () { fmt.Println("递归调用值为:" ,recursiveMine(5 ,10 )) fmt.Println("自底向上调用为:" ,bottomToTopMine(5 ,10 )) } func recursiveMine (n int , w int ) (value int ){ if n<=1 && w<P[0 ]{ return 0 }else if n==1 && w>=P[0 ]{ return G[0 ] }else if n>1 && w<P[n-1 ]{ return recursiveMine(n-1 ,w) } return max(recursiveMine(n-1 ,w),recursiveMine(n-1 ,w-P[n-1 ])+G[n-1 ]) } func bottomToTopMine (n int ,w int ) (a int ){ var value[10 ]int var nextValue[10 ]int var i,j = 0 ,1 for ;i<w;i++{ if i+1 >=P[0 ] { value[i]=G[0 ] }else { value[i]=0 } } for ;j<n; j++ { for i=0 ;i<10 ;i++{ if i+1 <P[j] { nextValue[i]=value[i] }else { if i+1 >P[j]{ nextValue[i]=max(value[i],value[i-P[j]]+G[j]) }else { nextValue[i]=max(value[i],G[j]) } } } value=nextValue } return value[w-1 ] } func max (a int ,b int ) (value int ){ if a>b { return a } return b } 递归调用值为: 900 自底向上调用为: 900
相关引用 漫画:什么是动态规划?