参考HDU2064和2077
汉诺塔2:a,b,c三柱,n个圆盘,大的不能放在小的上面,每次移动一个
汉诺塔3:a,b,c三柱,n个圆盘,大的不能放在小的上面,每次移动一个,且只能在相邻柱子之间移动
汉诺塔4:a,b,c三柱,n个圆盘,大的不能放在小的上面,每次移动一个,且只能在相邻柱子之间移动;(加上一个特例:只有最大的圆盘可以放在小的上面,即第n个圆盘)
一个一个解决:
声明:
1.文中x1->x2表示从x1移动一个圆盘到x2
2.函数名mx(int n,a,b,c)表示从a移动n个圆盘经过b到c
汉诺塔2:
当n==1;a柱只有一个圆盘,直接a->c
当n>1;先将a柱的n-1个圆盘移动到b,然后a->c,将剩下的n-1个圆盘从b移动到c;
m1(int n,a,b,c){
if(n==1) a->c;
else{
m1(n-1,a,c,b);
a->c;
m1(n-1,b,a,c);
}
}
可以得出
1.m(1)=1
2.m(n)=m(n-1)*2+1;
然后不论使用函数递归还是数组递归都可以解决问题,不过要提醒,在刷题是用函数递归因为时间超出是不能提交成功的。下面两种情况也是如此,我会在汉诺塔4中详细说明两种代码,前两种不予解决问题代码
汉诺塔3:
1.当n==1时,直接a到b到c
2.当n>1时,先把n-1个圆盘由a移动到c,在把第n个圆盘从a移动到b,在把n-1个圆盘从c移动到a,在把第n个圆盘从b移动到c
m1(int n,a,b,c){
if(n==1)a->b->c;
else{
m1(n-1,a,b,c);
a->b;
m1(n-1,c,b,a);
b->c;
m1(n-1,a,b,c);
}
}
由此可以得到
1.m1(1)=1
2.m1(n)=m1(n-1)*3+2;
汉诺塔4(题目来源HDU2077):
这个问题网上的答案我只能说我看不懂,看的懂就不会费这些时间研究了!
先给出我最开始的想法:
函数m(int n,a,b,c)(附:解决汉诺塔4问题)
当n==1; 直接a->b->c;
当n>1;先把n-1圆盘从a移动到b,在把第n个圆盘a->b->c;然后把n-1个圆盘从b移动到c;
函数m1(int n,a,c,b) (附:解决函数m中的"把n-1个圆盘从a移动到b"
当n==1;直接b->c;
当n>1;先把n-1个圆盘从a移动到c;再把第 n个圆盘从a移动到b;再把n-1个圆盘从c移动到b
m1(int n,a,c,b)
{
if(n==1)a->b;
else{
m3(n-1,a,b,c);
a->b;
m1(n,c,a,b);
}
函数m2(int n,b,a,c)(附:解决函数m中“把n-1个圆盘从b移动到c”
当n==1;直接直接b->c
当n>1:先把n-1个圆盘从b移动到a;再把第n个圆盘从b移动到c;再把n-1个圆盘从a移动到c
m2(int n,b,a,c){
if(n==1)b->c;
else{
m2(n-1,b,c,a)
b->c;
m3(n-1,a,b,c);
}
函数m3(int n,a,b,c)(附:解决m1中“先把n-1个圆盘从a移动到c”和m2中的“再把n-1个圆盘从a移动到c”
当n==1;直接a->b->c
当n>1;先将n-1个圆盘从a移动到c;再把第n个圆盘从a移动到b;再把n-1个圆盘从c移动到a;再把第n个圆盘从b移动到c;再把n-1个圆盘从a移动到c
m3(int n,a,b,c)
{
if(n==1) a->b->c;
else{
m3(n-1,a,b,c);
a->b;
m3(n-1,c,b,a);
b->c;
m3(n-1,a,b,c);
}
下面附上我递归函数的代码:
#include <stdio.h>
int c;
void m1(int n);
void m3(int n);
void m(int n){
if(n==1)c+=2;
else{
m1(n-1);
c+=2;
m1(n-1);
}
}
void m1(int n){
if(n==1)c+=1;
else{
m3(n-1);
c+=1;
m1(n-1);
}
}
void m3(int n){
if(n==1)c+=2;
else{
m3(n-1);
c+=1;
m3(n-1);
c+=1;
m3(n-1);
}
}
int main(){
int n,l;
scanf("%d",&n);
while(n--){
c=0;
scanf("%d",&l);
m(l);
printf("%d\n",c);
}
}
全局int用来记住总共移动次数,可以解决问题,但时间超了,提交失败
上面的几个函数可以总结为
m(n)=m1(n-1)+m2(n-1)+2;
m1(n)=m3(n-1)+m1(n-1)+1;
m2(n)=m2(n-1)+m3(n-1)+1;
m3(n)=m3(n-1)*3+2;
发现m1和m2函数似乎作用一样,把m2全部改为m1
m(n)=m1(n-1)*2+2;
m1(n)=m1(n-1)+m3(n-1)+1;
m3(n)=m3(n-1)*3+2;
这里动用数组解决:
题目里面的n最大为20,所以我先算出m1数组和m3数组的前20项目;最后简单调用,
提交成功
#include <stdio.h>
int main(){
int n,num;
scanf("%d",&n);
long long m,m1[20],m3[20];
m3[0]=2;m1[0]=1;
for(int i=1;i<20;i++){
m3[i] = m3[i-1]*3+2;
m1[i] = m1[i-1]+m3[i-1]+1;
}
while(n--){
scanf("%d",&num);
m =(num==0)?0:((num==1)?2:2*m1[num-2]+2);
printf("%lld\n",m);
}
}
(全程码字,无功有苦,见谅)