题目描述
我们有从大到小放置的n个圆盘,开始时所有圆盘都放在左边的柱子上,按照汉诺塔游戏的要求我们要把所有的圆盘都移到右边的柱子上,请实现一个函数打印最优移动轨迹。
给定一个int n,表示有n个圆盘。请返回一个string数组,其中的元素依次为每次移动的描述。描述格式为: move from [left/mid/right] to [left/mid/right]。
示例1
输入:2
返回值 :[“move from left to mid”,“move from left to right”,“move from mid to right”]
B站视频讲解汉诺塔 该视频讲解很清楚,连递归如何写以及汉诺塔递归的详细过程都动态展示了出来。
注意:有些视频里讲解的东西,一会儿A,B,C,移动过来移动过去,直接给人弄懵。汉诺塔每一层的目标柱子编号是不一样的。
视频中讲解了递归的写法就如同多米诺骨牌一样,首先确定一开始的动作,你要推导第一个牌(出口条件);其次需要假定f(n-1) 是正确的,最后需要写出最后一个牌与倒数第二个牌之间的关系(递归表达式)。是不是很形象。
按照上面的方法,第一步,如果只有一个样例输出打印函数,输出函数的组成是从 起始位置到结束位置 。此外假定f(n-1) 是正确的,其次想想最后一个牌,和倒数第二个牌之间的关系,也就是n个圆盘和n-1个圆盘的关系。对于n个圆盘,要想让这第n个圆盘放置到3号杆子上,就需要将 其上面n-1个盘放置到 2 号盘上,然后把 n 号盘放到3号杆子上,最后把 n-1 个盘子从2号杆子上移动到3号杆子上。注意: 中间的杆子用的是 6-start-end来计算的。
class Solution {
public:
vector<string> res;
vector<string> getSolution(int n) {
// write code here
han(n,1,3);
return res;
}
void han(int n,int start,int end)
{
int other=6-start-end;
if(n==1) res.push_back(printS(start, end));
else
{
han(n-1,start,other);
res.push_back(printS(start, end));
han(n-1,other,end);
}
}
string printS(int from,int to)
{
string s,e;
if(from==2) s="mid";
else if(from==1) s="left";
else s="right";
if(to==2) e="mid";
else if(to==1) e="left";
else e="right";
return "move from "+s+" to "+e;
}
};