本身用Java写了一个前台进行四柱汉诺塔的移动演示,是按照最优次序进行移动的,连接里有详细的代码实现:https://download.csdn.net/download/qq_40285036/10841684ios
四柱汉诺塔,在A柱上有N个盘子,**最少**通过多少次移动能把盘子所有移动到D上?
令dp[ n ]表示有n个盘子时的最优值,从2的分析中能够看出
(1)先把k个盘子,从A柱通过C,D移动到B上。–>移动次数为 dp[ k ]
(2)再把A柱上的N-K个盘子,通过C,移动到D上(这个子问题就是三柱汉诺塔问题,他的移动次数为2^(n-k) - 1。)–>移动次数为 2^(n-k) - 1
(3)再把k个盘子,从B柱上通过A,C移动到D上。 –> 移动次数为dp[ k ]web
那么: dp[ n ] = 2 * dp[ k ] + 2^(n-k) - 1
枚举K值求最优,则最优子结构为:dp[ n ] = min(2 * dp[ k ] + 2 ^ (n - k) - 1), k = 1 … n
初始化 : dp[1] = 1(只有一个盘子,只须要一次移动);dp[2] = 3(两个盘子至少要移动三次)svg
#include <iostream> #include <algorithm> #include <cstring> #include <vector> using namespace std; #define N 100 #define INF 0x3f3f3f3f typedef long long ll; ll dp[N]; int optimalPath[N]; void TraceBack(vector<int> &path,int n) { if (optimalPath[n] == n) { path.push_back(n); return; } path.push_back(optimalPath[n]); TraceBack(path, optimalPath[n]); } int main() { int n; while (cin >> n, n) { for (int i = 1; i <= n; i++) dp[i] = INF; dp[1] = 1; dp[2] = 3; for (int i = 3; i <= n; i++) { for (int k = 1; k <= i; k++) { ll tmp = 2 * dp[i - k] + (ll)pow(2, k) - 1; if (dp[i] > tmp) { dp[i] = tmp; optimalPath[i] = k; } } } cout << "最优移动次数为: " << dp[n] << endl; vector<int> path; TraceBack(path, n); cout << "optimal path:" << endl; for (int i : path) { cout << i << " "; } cout << endl; } }