汉诺塔问题比较经典,这里修改--下游戏规则:
- 现在限制不能从最左侧的塔直接移动到最右侧,也不能从最右侧直接移动到最左侧,而是必须经过中间。
- 求当塔有N层的时候,打印最优移动过程和最优移动总步数。
解题思路:
如果剩下N层塔,从最上到最下依次为1~N,则有如下判断:
1.如果剩下的N层塔都在“左”,希望全部移到“中”,则有三个步骤。
1)将1~N-1层塔先全部从“左”移到“右",明显交给递归过程。
2)将第N层塔从“左”移到“中”。
3)再将1~N-1层塔全部从“右”移到“中”,明显交给递归过程。
2.如果把剩下的N层塔从“中”移到“左”,从“中”移到“右”,从“右”移到“中”,过程与情况1同理,一样是分解为三步,在此不再详述。
3.如果剩下的N层塔都在“左”,希望全部移到“右”,则有五个步骤。
1)将1~N-1层塔先全部从“左”移到“右”,明显交给递归过程。
2)将第N层塔从“左”移到“中”。
3)将1~N-1层塔全部从“右”移到“左”,明显交给递归过程。
4)将第N层塔从“中”移到“右”。
5)最后将1~N-1层塔全部从“左”移到“右”,明显交给递归过程。
4.如果剩下的N层塔都在“右",希望全部移到“左”,过程与情况3同理,一样是分解为五步,在此不再详述。
#include <iostream> #include <string.h> using namespace std; int hanoiRec(int layer, string src, string dst) { if (1 > layer) return 0; if (1 == layer) //只有一层时(递归的退出检测) { if ("mid" == src || "mid" == dst) //源端或目的端为中间的情况 { cout << "move 1 form " << src << " to " << dst << endl; return 1; } else //源端或目的端为非中间的情况(左/右) { cout << "move 1 form " << src << " to mid" << endl; cout << "move 1 form mid to " << dst << endl; return 2; } } //有多层的情况 if ("mid" == src || "mid" == dst) //源端或目的端为mid的情况(普通的汉诺塔问题) { //获得辅助端(左/右) string aux = ("left" == src || "left" == dst) ? "right" : "left"; //第一步,将1~layer-1层从源端移动到辅助端 int step1 = hanoiRec(layer - 1, src, aux); //第二步,将第layer层移动到目的端 int step2 = 1; cout << "move " << layer << " from " << src << " to " << dst << endl; //第三步,将1~layer-1层从辅助端移动到目的端 int step3 = hanoiRec(layer - 1, aux, dst); return step1 + step2 + step3; } else //源端和目的端为非mid的情况 { //第一步,将1~layer-1层从源端移动到目的端 int step1 = hanoiRec(layer - 1, src, dst); //第二步,将第layer层从源端移动到mid端(即mid端为辅助端) int step2 = 1; cout << "move " << layer << " from " << src << " to mid" << endl; //第三步,将1~layer-1层从目的端移动到源端 int step3 = hanoiRec(layer - 1, dst, src); //第四步,将第layer层从mid端移动到目的端 int step4 = 1; cout << "move " << layer << " from mid to " << dst << endl; //第五步,将1~layer-1层从源端移动到目的端 int step5 = hanoiRec(layer - 1, src, dst); return step1 + step2 + step3 + step4 + step5; } } int main() { int step = hanoiRec(2, "mid", "right"); cout << "It will move " << step << " steps." << endl; return 0; }