许多人一定很熟悉九连环(如下图)
九个环被串在一起,操作规则如下:第一个(右边)环可以任意装卸,如果第k个环没有被卸掉,而第k个环前边(右边)的所有环都被卸掉,则第k+1个环(第k个环左边的环)可以任意装卸(如果存在的话)。
用0表示此换被卸掉,1表示此环没有被卸掉,则九连环的每个状态可以用一个长度为9的二进制串来表示,如:111111001经过一次操作可以变成111111000,也可以变成111111011,111111111经过一次操作可以变成111111110,也可以变成111111101。
这是我八分钟盲拧九连环的视频:
九连环就是典型的递归
只需要up和down2个函数互相调用即可
对于初始状态111111111,要变成000000000,需要在main函数里面调用9次down函数
代码:
#include<iostream>
using namespace std;
int l[10];
void down(int n);
void up(int n)
{
if (l[n])return;
up(n - 1);
for (int i = n - 2; i > 0; i--)down(i);
cout << "上" << n << " ";
l[n] = 1;
}
void down(int n)
{
if (n*l[n] == 0)return;
up(n - 1);
for (int i = n - 2; i > 0; i--)down(i);
cout << "下" << n << " ";
l[n] = 0;
}
int main()
{
for (int i = 0; i < 10; i++)l[i] = 1;
for (int i = 9; i>0; i--)down(i);
return 0;
}
结果:
下1 下3 上1 下2 下1 下5 上1 上2 下1 上3 上1 下2 下1 下4 上1 上2 下1 下3 上1 下2 下1 下7 上1 上2 下1 上3 上1 下2 下1 上4 上1 上2 下1 下3 上1 下2 下1 上5 上1 上2 下1 上3 上1 下2 下1 下4 上1 上2 下1 下3 上1 下2 下1 下6 上1 上2 下1 上3 上1 下2 下1 上4 上1 上2 下1 下3 上1 下2 下1 下5 上1 上2 下1 上3 上1 下2 下1 下4 上1 上2 下1 下3 上1 下2 下1 下9 上1 上2 下1 上3 上1 下2 下1 上4 上1 上2 下1 下3 上1 下2 下1 上5 上1 上2 下1 上3 上1 下2 下1 下4 上1 上2 下1 下3 上1 下2 下1 上6 上1 上2 下1 上3 上1 下2 下1 上4 上1 上2 下1 下3 上1 下2 下1 下5 上1 上2 下1 上3 上1 下2 下1 下4 上1 上2 下1 下3 上1 下2 下1 上7 上1 上2 下1 上3 上1 下2 下1 上4 上1 上2 下1 下3 上1 下2 下1 上5 上1 上2 下1 上3 上1 下2 下1 下4 上1 上2 下1 下3 上1 下2 下1 下6 上1 上2 下1 上3 上1 下2 下1 上4 上1 上2 下1 下3 上1 下2 下1 下5 上1 上2 下1 上3 上1 下2 下1 下4 上1 上2 下1 下3 上1 下2 下1 下8 上1 上2 下1 上3 上1 下2 下1 上4 上1 上2 下1 下3 上1 下2 下1 上5 上1 上2 下1 上3 上1 下2 下1 下4 上1 上2 下1 下3 上1 下2 下1 上6 上1 上2 下1 上3 上1 下2 下1 上4 上1 上2 下1 下3 上1 下2 下1 下5 上1 上2 下1 上3 上1 下2 下1 下4 上1 上2 下1 下3 上1 下2 下1 下7 上1 上2 下1 上3 上1 下2 下1 上4 上1 上2 下1 下3 上1 下2 下1 上5 上1 上2 下1 上3 上1 下2 下1 下4 上1 上2 下1 下3 上1 下2 下1 下6 上1 上2 下1 上3 上1 下2 下1 上4 上1 上2 下1 下3 上1 下2 下1 下5 上1 上2 下1 上3 上1 下2 下1 下4 上1 上2 下1 下3 上1 下2 下1
一共341步
但是,玩过九连环的朋友都知道,从状态*11变成*00,或者从状态*00变成*11,只需要1步
也就是说,最右边的2个环可以一起装卸
这样,我们就需要调整输出了。
仔细说来,我们的目标是把所有的“下2 下1”换成“下21”,把所有的“上1 上2”换成“上12”
可以通过修改递归终止条件来实现,也可以把输出的结果入栈(或队列),在出栈(或队列)的时候进行合并,还可以直接把输出结果当成一个字符串,然后查找关键词替换。
查找关键词替换可以通过编程实现,也可以直接用word
总之结果如下:
下1 下3 上1 下21 下5 上12 下1 上3 上1 下21 下4 上12 下1 下3 上1 下21 下7 上12 下1 上3 上1 下21 上4 上12 下1 下3 上1 下21 上5 上12 下1 上3 上1 下21 下4 上12 下1 下3 上1 下21 下6 上12 下1 上3 上1 下21 上4 上12 下1 下3 上1 下21 下5 上12 下1 上3 上1 下21 下4 上12 下1 下3 上1 下21 下9 上12 下1 上3 上1 下21 上4 上12 下1 下3 上1 下21 上5 上12 下1 上3 上1 下21 下4 上12 下1 下3 上1 下21 上6 上12 下1 上3 上1 下21 上4 上12 下1 下3 上1 下21 下5 上12 下1 上3 上1 下21 下4 上12 下1 下3 上1 下21 上7 上12 下1 上3 上1 下21 上4 上12 下1 下3 上1 下21 上5 上12 下1 上3 上1 下21 下4 上12 下1 下3 上1 下21 下6 上12 下1 上3 上1 下21 上4 上12 下1 下3 上1 下21 下5 上12 下1 上3 上1 下21 下4 上12 下1 下3 上1 下21 下8 上12 下1 上3 上1 下21 上4 上12 下1 下3 上1 下21 上5 上12 下1 上3 上1 下21 下4 上12 下1 下3 上1 下21 上6 上12 下1 上3 上1 下21 上4 上12 下1 下3 上1 下21 下5 上12 下1 上3 上1 下21 下4 上12 下1 下3 上1 下21 下7 上12 下1 上3 上1 下21 上4 上12 下1 下3 上1 下21 上5 上12 下1 上3 上1 下21 下4 上12 下1 下3 上1 下21 下6 上12 下1 上3 上1 下21 上4 上12 下1 下3 上1 下21 下5 上12 下1 上3 上1 下21 下4 上12 下1 下3 上1 下21
刚好256步,256的2的8次方
实际上,无论是简化之前的341步,还是简化之后的256步,都满足f(n)=f(n-1)+2f(n-2)+1(这个递推式是比较显然的)
只不过简化之前的初始值是f(2)=2,f(3)=5,而简化之后的初始值是f(2)=1,f(3)=4
上面的2阶常系数齐次线性递推式还可以转化成1阶常系数齐次线性递推式。
对于状态000000000,要变成111111111,需要在main函数里面调用9次up函数
只需要修改main函数即可
代码:
int main()
{
for (int i = 0; i < 10; i++)l[i] =(i==0);
for (int i = 9; i>0; i--)up(i);
return 0;
}
结果:
上1 上2 下1 上3 上1 下2 下1 上4 上1 上2 下1 下3 上1 下2 下1 上5 上1 上2 下1 上3 上1 下2 下1 下4 上1 上2 下1 下3 上1 下2 下1 上6 上1 上2 下1 上3 上1 下2 下1 上4 上1 上2 下1 下3 上1 下2 下1 下5 上1 上2 下1 上3 上1 下2 下1 下4 上1 上2 下1 下3 上1 下2 下1 上7 上1 上2 下1 上3 上1 下2 下1 上4 上1 上2 下1 下3 上1 下2 下1 上5 上1 上2 下1 上3 上1 下2 下1 下4 上1 上2 下1 下3 上1 下2 下1 下6 上1 上2 下1 上3 上1 下2 下1 上4 上1 上2 下1 下3 上1 下2 下1 下5 上1 上2 下1 上3 上1 下2 下1 下4 上1 上2 下1 下3 上1 下2 下1 上8 上1 上2 下1 上3 上1 下2 下1 上4 上1 上2 下1 下3 上1 下2 下1 上5 上1 上2 下1 上3 上1 下2 下1 下4 上1 上2 下1 下3 上1 下2 下1 上6 上1 上2 下1 上3 上1 下2 下1 上4 上1 上2 下1 下3 上1 下2 下1 下5 上1 上2 下1 上3 上1 下2 下1 下4 上1 上2 下1 下3 上1 下2 下1 下7 上1 上2 下1 上3 上1 下2 下1 上4 上1 上2 下1 下3 上1 下2 下1 上5 上1 上2 下1 上3 上1 下2 下1 下4 上1 上2 下1 下3 上1 下2 下1 下6 上1 上2 下1 上3 上1 下2 下1 上4 上1 上2 下1 下3 上1 下2 下1 下5 上1 上2 下1 上3 上1 下2 下1 下4 上1 上2 下1 下3 上1 下2 下1 上9 上1 上2 下1 上3 上1 下2 下1 上4 上1 上2 下1 下3 上1 下2 下1 上5 上1 上2 下1 上3 上1 下2 下1 下4 上1 上2 下1 下3 上1 下2 下1 上6 上1 上2 下1 上3 上1 下2 下1 上4 上1 上2 下1 下3 上1 下2 下1 下5 上1 上2 下1 上3 上1 下2 下1 下4 上1 上2 下1 下3 上1 下2 下1 上7 上1 上2 下1 上3 上1 下2 下1 上4 上1 上2 下1 下3 上1 下2 下1 上5 上1 上2 下1 上3 上1