动态规划-扑克牌最快打完问题
当我们遇到一些复杂问题的时候,发现根本无从下手。仅能想到的办法就是穷举所有的可能方案,在所有可能的方案中找到最优的结果。这种情况往往会用到递归,而递归用得不好可能会导致栈溢出,而且时间复杂度得不到保障。
动态规划的实质就是穷举,它与递归不同的是动态规划采用的是从低到高操作,在操作的过程中记录每一步的局部最优解,后面的结果需要通过前面的局部最优解进行推导。
本人对动态规划问题做了大量的研究,发现在解决动态规划问题时往往采用两种思路:(1)第一种是由点及面、由小及大、层层递推。(2)第二种是后推法,也就是从后向前递推。本文主要是通过扑克牌问题来贯彻实践一下第一种方法。
扑克牌问题描述
一副扑克牌,牌的面值有:A 1 2 3 4 5 6 7 8 9,每种面值的牌的数目<=4,打牌的规则如下:
1.出单张,例如出一张A
2.出对子,例如出一对11
3.五张顺子,例如:A 1 2 3 4或者4 5 6 7 8
2.三连对,例如:1 1 2 2 3 3
现在该出各种牌的数目,例如:1 1 1 2 2 2 2 2 1 1,求最少打多少次能把手里的牌打完。
问题分析
我解决这个问题采用的方法就是由点及面,由小及大,层层递推的思路。所谓由小及大,就是在思考的过程中,假设只有A面值的牌,求出结果,然后求出只有A和1两种面值的牌求出结果,这样层层递推,直到求出最后的结果。假设给出的各面值的牌的数目为: v e c = { a 1 , a 2 , a 3 , a 4 , a 5 , a 6 , a 7 , a 8 , a 9 , a 10 } vec=\{a_{1} ,a_{2}, a_{3}, a_{4}, a_{5}, a_{6}, a_{7}, a_{8}, a_{9},a_{10}\} vec={ a1,a2,a3,a4,a5,a6,a7,a8,a9,a10},其推导过程如下所示:
n = 1 d p [ 0 ] = v e c [ 0 ] / 2 + v e c [ 0 ] % 2 n=1 \quad dp[0]=vec[0]/2+vec[0]\%2 n=1dp[0]=vec[0]/2+vec[0]%2
n = 2 d p [ 1 ] = v e c [ 1 ] / 2 + v e c [ 1 ] % 2 + d p [ 0 ] n=2 \quad dp[1]=vec[1]/2+vec[1]\%2+dp[0] n=2dp[1]=vec[1]/2+vec[1]%2+dp[0]
n = 3 d p [ 2 ] = m i n { v