【声明】:转载自https://www.cnblogs.com/mu-ye/p/7895963.html
题意:经典的汉诺塔问题是有3根柱子,第一根柱子上有n个盘子,下面盘子比上面盘子大,要求把所有盘子移到第三根柱子上,过程中不能使得上面的盘子大于下面的盘子,且每次只能移动一个盘子,问最少需要多少步。
一开始想的是用普通递归,也就是状态空间搜索路径的方法,这样传的参数比较多。
在尝试n为比较小的数时想到了用动态规划的方法。
思路:d(n)为把n个盘子移到另一个柱子上的步数。那么d(n)等于把上面n-1个盘子移到非目标柱子上+把最后一个盘子移到目标柱子上+把非目标柱子上的n-1个盘子移到目标柱子上(这样划分,状态就出来了,是吧),即d(n)=d(n-1)+1+d(n-1)=2*d(n-1)+1。动态规划的状态转移方程,边界条件是盘子为1时移动一步,返回1。
解释一下,把上面n-1个盘子移动到非目标柱子上相当于把n-1个盘子移动到另一个柱子(即d(n-1)),因为剩下2根柱子没什么区别,把非目标柱子上的n-1个盘子移动到目标柱子上也相当于把n-1个盘子移动到另一个柱子上(即d(n-1)),也是因为剩下2根柱子没什么区别,都可以忽略最大的那个盘子。
感觉用动态规划的好处就是,有最优子结构,不用考虑具体的步骤。
(一年没做过动态规划的题了,写的仔细点。。。)
#include<iostream> using namespace std; int d(int n) { if(n == 1) { return 1; } return (2 * d(n - 1) + 1); } int main() { int n; while(cin >> n) { cout << d(n) << endl; } return 0; }