汉诺塔算法是什么?

iTunes 的 App Store 中的“汉诺塔+”
正在打开 iTunes Store。如果 iTunes 不自动打开,在 Dock 或 Windows 桌面上点击 iTunes 图标。进度指示器
正在打开 iBooks Store。如果 iBooks 未打开,请在 Dock 中打开 iBooks App。进度指示器
如要轻松整理及新增数码媒体收藏,iTunes 是全世界最简单的工具。
我们在您的电脑上找不到 iTunes。 要购买和下载PandaWebsoft的汉诺塔+,请立即获取 iTunes。
已经有 iTunes 了? 现在点击「我有 iTunes」以打开 iTunes。
开发商:PandaWebsoft
打开 iTunes 以购买和下载 App。
这是一款能够让你拥有自己的金字塔的游戏。在游戏的过程中,通过搬运和堆砌石头来建造金字塔。游戏共有10个关卡,当全部关卡都通过时,你的金字塔便建造完成!游戏规则:1. 将石头由小到大(最下方的最大块)的顺序堆砌在最右侧2. BATTLE MODE下,画面顶部的时间条的时间会不断流逝,必须在时间完全流逝之前完成石头的搬运3. 使用道具”魔法沙漏“能够拾回已经流逝了的时间(该道具随着使用次数的增加,道具效果也越来越明显,效果最佳时可以拾回100%的流逝时间4. 道具可以通过游戏中取得的Score积分兑换最后顺带一提的是,当你每通过一关,每盖建一层金字塔时,系统都会提示出累积的建造花费时间。可以看看你竣工一座金字塔究竟需要花费多少时间,或许你可以成为这个世界上建造金字塔最快速的”法老王“ :)
iPhone 屏幕快照
稍贵了点,但配音,设计都不错呢,很精致,若有存档就更好了!
用户购买的还有
?6.00类别: 版本: 1.0大小: 62.3 MB语言: 英语开发商: SYO GAHEI兼容性: 需要 iOS 3.2 或更高版本。与 iPhone、iPad、iPod touch 兼容。
还没有足够多的评分,因此无法显示此应用软件当前版本的平均评分。
PandaWebsoft 的更多 iPhone App您还未登陆,请登录后操作!
七层的汉诺塔怎么玩?
其实汉诺塔只要掌握规律,多少层都是一样的。最重要的是第一块放在哪儿,单数层的汉诺塔一定要放在第三柱,双数层的要放在第二柱。如果你会六层的汉诺塔,(将第一块放在第三柱),将六块都移到第二柱,最后一块移到第三柱,再如前法将上面六块都移到第三柱。就OK了。
您的举报已经提交成功,我们将尽快处理,谢谢!
大家还关注辞职了,散分!并改进一下汉诺塔的算法。
[问题点数:40分,结帖人SmallYamateh]
辞职了,散分!并改进一下汉诺塔的算法。
[问题点数:40分,结帖人SmallYamateh]
不显示删除回复
显示所有回复
显示星级回复
显示得分回复
只显示楼主
相关帖子推荐:
匿名用户不能发表回复!|
每天回帖即可获得10分可用分!小技巧:
你还可以输入10000个字符
(Ctrl+Enter)
请遵守CSDN,不得违反国家法律法规。
转载文章请注明出自“CSDN(www.csdn.net)”。如是商业用途请联系原作者。1977人阅读
在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘,求把圆盘从下面开始按大小顺序重新摆放在另一根柱子上需要移动多少次。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。
我们可以拿n=3的时候举例子:
易知f(1)=1,f(2)=3,f(3)=7……;
当n=2时候(1,2,3分别表示小中大三块盘子):
当n=3时候:
n=3的前三步就是重复n=2时候,把小的两块移动到另一个一个柱子。
然后就是将3移动到另一块柱子上,在继续重复n=2把小的两块移动到另一个(指存在3的一个)柱子上。
扩展到n,即f(n)=2*f(n-1)+1 & &&
这就变成了递归问题!!
只计算次数,简单的c++程序如下:
#include &iostream&
int main()
int num,cont=0,a=1;
cout&&&请输入需要移动的盘子数目:&&&
int val(int);
//函数声明
if(num==0){
cout&&&输入的数字必须大于0!&&&
return -1;
cout&&&需要&&&val(num)&&&次&&&
int val(int n){
if(n==1) c=1;
else c=2*val(n-1)+1;
显示步骤:
每个步骤都是
将n-1个盘子从A移到B,把最下面个移到C,然后把N-2个从B移到A,第N-1个移到C,如此继续下去。
#include&iostream&
int main()
void hanoi(int n,char one,char two,char three);
cout&&&输入盘子数:&;
hanoi(m,'A','B','C');
void hanoi(int n,char one,char two,char three)
void move(char x,char y);
if (n == 1)
move(one,three);
hanoi(n-1,one,three,two);
move(one,three);
hanoi(n-1,two,one,three);
void move(char x, char y)
cout&&x&&&--&&&&y&&
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:264703次
积分:5219
积分:5219
排名:第2025名
原创:257篇
转载:13篇
评论:111条
(1)(2)(6)(2)(5)(4)(7)(11)(35)(10)(3)(12)(10)(84)(7)(8)(8)(38)(17)1369人阅读
看了一下杭电的各种汉诺塔问题,遇到些奇奇葩葩的小问题,也有很多很好的思想,比如最后一题,来来回回的颠倒很有意思。总结一下;
Pro.ID 1207 :
意思是给把原始的汉诺塔问题中的3根柱子改为4根。做了半天各种WA。查了一下,有一篇文章详细讲了一下,还做出了递归公式以及数学公式:
地址如下:.
代码如下:
#include&cstdio&
#include&cmath&
#include&algorithm&
//F(n)=min(2*F(n-r)+2^r-1),(1≤r≤n)
int main()
long long Min,f[65];
for(int i=3;i&=65;i++)
for(int j=1;j&i;j++)
Min=min(2*f[j]+pow(2.0,i-j)-1,Min*1.0);
while(~scanf(&%d&,&n))
printf(&%lld\n&,f[n]);
按照公式写就是了,写的时候需要注意一下精度问题。2^r可以写为1&&r,不过因为数字常数1默认是32位,所以如果要使用位移的话,一定要先声明一个longlong类型的变量来进行位移,否则 就会出现溢出错误,这个我纠结了一阵子,感觉没错,一提交就WA,然后试了试64发现果然是负数。
哎,基础还是不扎实啊。
用pow函数因为返回的是一个double类型,min函数里比较也是用double来做的,只是在最后赋值的时候取int型就可以,所以不会出错。
Pro.ID &1995&汉诺塔V
这个是普通的汉诺塔,最优的步数是2^n-1,只不过问的第i个盘子移动的次数。依然是用递归,在纸上画画就能出来。
注意了,第i盘子,不用考虑底下的盘子,只用看之上的经过一个柱子到达目的地。即F[n]=2*f[n-1]
#include&iostream&
__int64 s[61] = {0, 1};
int n, i, t,
for(i = 2; i & 61; i++)
s[i] = s[i - 1] * 2;
while(t--)
cin && n &&
cout && s[n - m + 1] &&
}Pro.ID&汉诺塔VI
是问所有步骤,注意不是最优的,是全部(当然不包括错误的步骤)
每一个盘子可以放到3根柱子的任意一个,所以是3^n。比如正确的是直接从a-&c,现在可以a-&b然后在b-&c,就是多了2种。每一个都多了2种,所以是3^n。
#include&iostream&
#include&math.h&
#include&stdio.h&
int main()
__int64 t,n,i;
__int64 sum,a[100]={3,};
while(cin&&t)
while(t--)
for(i=1;i&n;i++)
a[i]=a[i-1]*3;
cout&&a[n-1]&&
}Pro.ID 1997&汉诺塔VII
题目是说,给定某一时刻的三个柱子上的盘子,问这个是不是符合最优解过程中某一时刻的状态。
对一个含有n个盘子,从A柱移动到C柱借助B柱的汉诺塔,第n个盘子移动到C柱过程是这样子的:首先将其余的n-1个盘子移动到B柱,然后第n个盘子直接移动到C柱。在这过程中,第n个盘子只出现在A柱和C柱两个柱子上,也即第n个盘子不可能出现在B柱上。因此对于当前移动的盘子,只需检查其所在的柱子是否符合这个要求,如果出现在B柱上,则显然进入了错误移动中。这是本题求解思想精髓所在。
具体的内容请参考这篇博客:
代码就不贴了,上边这个博客里写的很详细。
Pro.ID 2064&汉诺塔III
还是递推:num[i]=3*num[i-1]+2;
不解释了,代码如下:
#include&iostream&
#include&cstdio&
#include&cstring&
#include&cmath&
unsigned long long num[36];
int main()
for(int i=3;i&=35;i++)
num[i]=3*num[i-1]+2;
while(~scanf(&%d&,&n))
cout&&num[n]&&
Pro.ID 2077&汉诺塔IV(参考了的博客)
好无聊啊,把上边的规则给改了,只是最大的可以放上边。其实感觉这个题目跟之前那个1027题目有点想通之处,在1027中说的是4根柱子,所以通用的这3个步骤其实并非最优解:
从柱借助柱子将个盘子移动到柱上。
将个通过柱简单的移动到柱上【步骤】。
从柱借助,柱子将个盘子移动到柱上。
如果有n个盘子,则需要前n-1个挪到中间的盘子上,然后最大的盘子挪到最右面,需要两步,把前(n-1)个盘子从左边挪到中间是和从中间挪到右边需要相同的次数。而a数组中存放的就是那个前n-1个盘子挪动到相同位置需要的次数。结果即为a[i-1]*2+2。
所以我直接想成了是f[n]=2*f[n-1]+2,结果错了。【因为是需要n-1个盘子前进一步】
而求a数组需要用到递推。公式为第i个为前n-1个移动次数的三倍加一,简化到两个盘子,小的先移动两次到最右边,大的移到中间,然后小的在移回中间,小的移动了三次,而大的移动了一次,就使他们全部挪动了一个位置
所以代码如下:
#include&stdio.h&
int a[20]={0,1};
int main()
for(i=2;i&21;i++)
a[i]=3*a[i-1]+1;
scanf(&%d&,&T);
while(T--)
scanf(&%d&,&i);
printf(&%d\n&,2*a[i-1]+2);
Pro.ID 2175&汉诺塔IX
普通汉诺塔,问在最优步骤中的第i步是哪一个盘子,跟1995那个题目刚好相反。不过这个有点像数论题。
这样想,假设是4个盘子,考虑第三个,在第4步的时候将3盘从A移动到C【设目的地是B】,此时1,2盘在B上,设时间为T,然后将1,2盘移动到C上,(需要3步)再把4盘移动到B上,此时的格局为4盘在B上,1,2,3,在C上,距T过去了1+3=4步,那么3号盘什么时候再动呢?把1,2移走,3就可以放到B上了,移走1,2需要花费3个步骤,因此距T4+3+1也就是第8步,总体是第12步时,3号盘子会再次移动。现在看明白了吧,就是基数倍的2^(i-1)时,i号盘子会移动。
代码如下:
#include&iostream&
int main()
__int64 a[65];
__int64 i,n,r;
for(i=2;i&=63;i++)
a[i]=2*a[i-1];
while(~scanf(&%I64d%I64d&,&n,&m),n+m)
for(i=1;i&=n;i++)
if(r%2==1&&m%a[i]==0)
printf(&%I64d\n&,i);
Pro.ID 2184&汉诺塔VIII
感觉这个题目非常的好,挺有意思的,问普通汉诺塔,N个盘子,在最优解的第M步时,每个柱子上的盘子的状态。
想了半天,也没什么思路,但有一点是绝对可以确定的,就是一般解简单汉诺塔过程的问题都是使用递归,可以得到全部过程,但是当N稍微到10以上的时候必然递归很慢,所以直接递归模拟必然是错误的,但是根据上一题目,第i个步移动哪一个盘子中确定的,第K个盘子在 &奇数*2^(K-1)时移动可以得到些思想,必然是根据步数来确定盘子。
但是想了老半天也不太清楚那个递归改怎么写,好像每一次判断都要做除法到是可以确定某一个盘子,但是如何确定所有的盘子呢?纠结啊
查了半天,找到了一个大神的代码。
讲的非常的详细,我把思路以及代码粘过来大家分享一下:
定义数组a,其中a[i]表示完成一次i层汉诺塔移动的次数。
指针o,p,q分别表示三个位置。
起始状态为n层都在o上,要往q方向移动。
然后分成两种情况:
m&=a[n-1];
此时,第n层没机会移动,那么就相当于o上的n-1层往p上移动。
使其状态和起始状态一致,我们要交换p和q。
此时,先进行到下面状态,上面n-1层移动到p位置,第n层移动到q位置,消耗了a[n-1]+1次移动。
接下来就变成p上的n-1层往q上移动,只要交换o,p,令m=m-a[n-1]-1即可。
通过上述操作,都可以得到第n层的位置,并且问题变成n-1层都在o上,要往q方向移动。
#include&cstdio&
#include&algorithm&
#include&iostream&
int main()
unsigned __int64 m,a[64];
int row[3][66];
for(int i=2;i&=63;i++)
a[i]=a[i-1]*2+1;
scanf(&%d&,&t);
while(t--)
scanf(&%d %I64u&,&n,&m);
int *start,*mid,*
start=row[0];
mid=row[1];
end=row[2];
*start=*mid=*end=1;
if(m&=a[n])
*(start+*start)=n+1;//从第二个位置开始记录盘子
(*start)++;//第一个位置表示的是这个柱子一共有多少个盘子
swap(end,mid);
*(end+*end)=n+1;
swap(start,mid);
m-=(a[n]+1);
for(int i=0;i&3;i++)
printf(&%d&,row[i][0]-1);
for(int j=1;j&row[i][0];j++)
printf(& %d&,row[i][j]);
printf(&\n&);
Pro.ID&汉诺塔 X
进一步加强条件,在求第m步时是哪个盘子动,怎么动。
必然递归啊。把上上个题目修改就可以了。具体的就不多说了,在注释里有详细解释
#include&iostream&
__int64 a[65];
void solve(int n,__int64 m,int start,int end)
int third=6-start-//得到第3跟柱子
__int64 mid=a[n];
if(m==mid) //如果是当前盘子移动,直接从start--&end
printf(&%d %d %d\n&,n,start,end);
if(m&mid)//当前盘子无法移动,必然是上边的某个盘子动,并且移动一定是到third号柱子上,递归求解
solve(n-1,m,start,third);
else//需要先移动当期盘子下部的盘子(参考2184题目)
solve(n-1,m-mid,third,end);
int main()
for(int i=2;i&=63;i++)
a[i]=2*a[i-1];
while(~scanf(&%d&,&t))
while(t--)
scanf(&%d%I64d&,&n,&m);
solve(n,m,1,3);
最后一个Pro.ID &2587:很O_O的汉诺塔
真心是跪了,
感谢的详细讲解,这里已经写的很清楚了:
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:86355次
积分:1570
积分:1570
排名:第12221名
原创:66篇
评论:79条
(1)(3)(1)(3)(6)(1)(2)(1)(2)(1)(2)(8)(15)(13)(7)(2)(1)

我要回帖

更多关于 汉诺塔算法 的文章

 

随机推荐