汉诺塔

牛牛的汉诺塔

本小妞迷上赌 提交于 2020-02-08 19:19:00
题目链接 题目描述 汉诺塔是一个经典问题,相传在古印度圣庙中,有一种被称为汉诺塔(Hanoi)的游戏。该游戏是在一块铜板装置上,有三根杆(编号A、B、C),在A杆自下而上、由大到小按顺序放置n个金盘。游戏的目标:把A杆上的金盘全部移到C杆上,并仍保持原有顺序叠好。操作规则:每次只能移动一个盘子,并且在移动过程中三根杆上都始终保持大盘在下,小盘在上,操作过程中盘子可以置于A、B、C任一杆上。 牛牛很快就理解了代码的意思并且写出了求解汉诺塔的程序,他现在想研究汉诺塔的规律。 请你统计以下信息:A->B,A->C,B->A,B->C,C->A,C->B的次数,以及所有移动的总步数。 思路 总步数好算,是 ,然后就是打表大法 , 怪我太菜 打表后,找规律,如果把上述的信息以一个数组 ~ 存放的话,可以发现 n为奇数: f[i][1] = f[i - 1][1]; f[i][4] = f[i - 1][4]; f[i][5] = f[i - 1][5]; f[i][6] = f[i - 1][5] * 2 + i / 2; f[i][2] = f[i][6] + (i + 1) / 2; f[i][3] = f[i][6]; n为偶数: f[i][2] = f[i - 1][2]; f[i][3] = f[i - 1][3]; f[i][6] = f[i - 1][6]; f[i][5] =

2.8 [hduoj] 2077 汉诺塔IV

。_饼干妹妹 提交于 2020-02-08 17:01:32
Problem Description 还记得汉诺塔III吗?他的规则是这样的:不允许直接从最左(右)边移到最右(左)边(每次移动一定是移到中间杆或从中间移出),也不允许大盘放到小盘的上面。xhd在想如果我们允许最大的盘子放到最上面会怎么样呢?(只允许最大的放在最上面)当然最后需要的结果是盘子从小到大排在最右边。 Input 输入数据的第一行是一个数据T,表示有T组数据。 每组数据有一个正整数n(1 <= n <= 20),表示有n个盘子。 Output 对于每组输入数据,最少需要的摆放次数。 Sample Input 2 1 10 Sample Output 2 19684 #include<stdio.h> int n,i,j; long long z(int t) { long long res=0; for(i=0;i<t-1;i++) { int temp=1; for(j=0;j<i;j++) temp*=3; res+=temp; } return res; } void main() { while(scanf("%d",&n)!=EOF) { while(n--) { int k; scanf("%d",&k); printf("%lld\n",2*z(k)+2); } } } 我在脑子里模拟这个场景发现,完成一个n层的汉诺塔的规律在于去除最后一层,即最大那个

汉诺塔问题

落爺英雄遲暮 提交于 2020-02-06 21:18:13
算法思想 对于汉诺塔问题,当只移动一个圆盘时,直接将圆盘从 A 针移动到 C 针。若移动的圆盘为 n(n>1),则分成几步走:把 (n-1) 个圆盘从 A 针移动到 B 针(借助 C 针);A 针上的最后一个圆盘移动到 C 针;B 针上的 (n-1) 个圆盘移动到 C 针(借助 A 针)。每做一遍,移动的圆盘少一个,逐次递减,最后当 n 为 1 时,完成整个移动过程。 因此,解决汉诺塔问题可设计一个递归函数,利用递归实现圆盘的整个移动过程,问题的解决过程是对实际操作的模拟。 其数学规律: 设f(n)为将n个圆盘移动到目标针的步数。则将n个盘从原有针x移动到目标针Y时: (1)先将第1到第n-1个盘从目标针X移动到多余针Z上,即需要f(n-1)步。 (2)将原有针的第n盘移到至目标针Y,即需要1步。 (3)将第1到第n-1个盘从多余针Z移动到目标针Y上,即需要f(n-1)步。 、故f(n)=2f(n-1)+1-> f(n)+1=2[f(n-1)+1]->f(n)+1=[2^(n-1)]* [f(1)+1]。 因为f(1)=1,故f(n)=2^n-1;可得出移动n个盘子需要经历2^n-1步。 #include<stdio.h> #include<ctype.h> #include <stdlib.h> void move(char one,char two); void han(int

HDOJ 1995 汉诺塔V

元气小坏坏 提交于 2020-02-06 04:16:40
HDOJ1995 汉诺塔V 题目描述 解题思路 题目需要求在移动整个汉诺塔时,指定盘块的移动次数。我们可以通过观察法发现,汉诺塔的从下往上每个盘的移动次数时固定的,分别是1,2,4,8依次往上增加,这个规律可以理解为上层n的移动次数必为下层n+1的两倍,因为下层的每1次移动,必须上层先借助辅助柱进行移动,因此上层会多出的1次移动,所以上层的移动是下层的2倍。 代码 #include < iostream > #include < string > #include < string . h > #include < algorithm > #include < math . h > #include < stdlib . h > using namespace std ; long long quick_pow ( long long base , int index ) { long long sum = 1 , x ; while ( index != 1 ) { x = base ; if ( index % 2 == 0 ) { base *= base ; index /= 2 ; } else { sum *= x ; index -- ; } } sum *= base ; return sum ; } int main ( int argc , char **

(Java)递归实现汉诺塔

巧了我就是萌 提交于 2020-02-05 09:25:28
标题:递归实现汉诺塔 //题目详细描述 :(前提:第一个柱子上的盘子是按顺序从小到大放置的)将第一个柱子上的所有盘子,先从小盘子开始,最终移动到最后一个盘子上,也是按照顺序,从上到下的盘子是从小到大放置的,一次只能移动一个盘子。(大盘子不能放在小盘子上面 ) //核心思想 :n代表盘子总个数,source原柱子,dest目标柱子 【代码演示:】 public class Hannoi { //三个盘子的标号为0,1,2 public static void move ( int n , int source , int dest ) { if ( n == 1 ) { System . out . printf ( "从 %d 移到 %d%n" , source , dest ) ; return ; } int other = 3 - source - dest ; move ( n - 1 , source , other ) ; System . out . printf ( "从 %d 移到 %d%n" , source , dest ) ; move ( n - 1 , other , dest ) ; } public static void main ( String [ ] args ) { move ( 3 , 0 , 2 ) ; } } 【运行结果:】 来源:

关于汉诺塔的一些思考-Python/C

北战南征 提交于 2020-02-05 01:24:43
關於漢諾塔的一些思考-Python 漢諾塔規則 漢諾塔的傳説 如何移動 移動n個金盤需要的步驟 Python的遞歸實現算法-網傳寫法 另一個基於自己思考寫出來的Python實現 參考 漢諾塔規則 有三根杆子A,B,C。A杆上有 N 個 (N>1) 穿孔圓盤,盤的尺寸由下到上依次變小。要求按下列規則將所有圓盤移至 C 杆: 1.每次只能移動一個圓盤; 2.大盤不能疊在小盤上面。 漢諾塔的傳説 傳說越南河內某間寺院有三根銀棒,上串 64 個金盤。寺院裏的僧侶依照一個古老的預言,以上述規則移動這些盤子;預言說當這些盤子移動完畢,世界就會滅亡。 如何移動 如果n = 1 , 直接A -> C. 如果n = 2 , 稍稍複雜, A -> B, A -> C, B -> C. … Part1: 我們可以把移動n個金盤的問題分解爲三步驟: 1.把上面n-1個金盤從A柱移動到B柱上; 2.把第n個金盤從A柱移動到C柱; 3.最後把在B柱上的n-1個金盤移動到C柱上。 Part2: 至於如何將上面n-1個金盤從A柱移動到B柱上,我們又可以把問題分解為三步驟: 1.把上面n-2個金盤從A柱移動到C柱上; 2.把第n-1個金盤從A柱移動到B柱; 3.最後把在C柱上的n-2個金盤移動到B柱上。 Part3: 那麽問題又來了,如何將上面n-2個金盤從A柱移動到C柱上,我們又可以把問題分解為三步驟: … 綜上

汉诺塔问题

随声附和 提交于 2020-02-05 00:05:03
汉诺塔问题 问题描述: 1.有三根柱子,在其中一个柱子上,从上到下套着N个从小到大的盘子 2.要求把左边所有的盘子移动到右边 3.每次只能移动一个盘子 4.大盘子不能放置在小盘子之上 需要将左侧的盘子,按照大的在下,小的在上的规则,全部移动到右侧(如下) 把a柱的n个盘子移动到c柱需要几步: 1.把前n-1个盘子都移动到b柱 2.把最大的盘子(第n个)移动到c柱 3.把b柱上的n-1个盘子移动到c柱 Java实现代码 package com . xingyun . digui ; public class HanNoTa { /* * 汉诺塔问题: * */ public static void main ( String [ ] args ) { hanNoTa ( 5 , 'a' , 'b' , 'c' ) ; } /* * 解决思路,一共分为两种情况,第一种是只有一个盘子,第二种是有多个盘子 */ /** * * @param n 盘子个数 * @param from 起始的柱子 * @param in 第二个柱子 * @param to 目标柱子 */ /* * 整个过程一共分为3步, * 第一步,将除了最下面的一个盘子外,其他盘子都移动到中间位置的柱子上面 * 第二步,将最后一个盘子移动到目标位置 * 第三部,将中间位置上的所有盘子全部移动到目标位置 * *

汉诺塔

二次信任 提交于 2020-02-04 11:22:31
汉诺塔递归 #include <bits/stdc++.h> using namespace std; int n; /* 把 N- 1个从A经过C移动到B,最后一个从A到C N- 1个在B上,经过A移动到C */ void hanuoti(int n,char A,char B,char C){ if(!n) return; else{ hanuoti(n - 1,A,C,B); //cnt++;记录移动的次数 printf("Move disk %d from %c to %c\n",n,A,C); hanuoti(n - 1,B,A,C); } } int main(){ scanf("%d",&n); hanuoti(n,'A','B','C'); return 0; } 用递归计算移动容易超时, 借助公式 2^n - 1 当数据太大时,公式无效,算不出大数 例如: P760通天之汉诺塔 #include <bits/stdc++.h> using namespace std; int n; stringstream b; string c; int main(){ //freopen("out","w",stdout); cin >> n; b.precision(0); b << fixed << pow(2.0L,n); c = b.str(); c[c.length

1207 ACM 汉诺塔II 数学

痞子三分冷 提交于 2020-02-03 21:04:57
题目: http://acm.hdu.edu.cn/showproblem.php?pid=1207 中文题目,在原来三个柱子的情况下(汉诺塔一),增加了一个柱子,难度也增加了。 思路: 思考时尽量和汉诺塔一联系起来。 1 ,先看汉诺塔一的情况 只有一个盘子时,只需挪动一步;假如n个盘子要移动An步,则有n+1个盘子可以先通过An步把上面的n个盘子挪到第二个柱子上,再挪最大的盘子,最后把n个盘子挪到大的上面,总共2An+1步,则有 A(n+1)=2An+1 。 以上式子可推得 An=2^n-1 。 2,回过来看该題,该题多加了一根柱子,现在有四根柱子了,分别是a,b,c,d,计算将n个盘从第一根柱子a全部移到最后一根柱子d上所需的最少步数。 设F[n]为所求的最小步数,则有当n=1时,F[n]=1;当n=2时,F[n]=3;这里同经典汉诺塔一样,将移动盘子的任务分为三步: 一,将x(1<=x<=n)个盘从a柱依靠b,d柱移到c柱,这个过程需要步数设为F[x](依靠两个柱子); 二,将a柱上剩下的n-x个盘依靠b柱移到d柱(此时不能依靠c柱,c柱上的所有盘都比a柱上的盘小),移动方式相当于是一个汉诺塔1版,这个过程需要的步数为2^(n-x)-1(汉诺塔一)(依靠一个柱子); 三,将c柱上的x个盘依靠a,b柱移到d柱上,这个过程同样需要的步数为F[x]; 经过以上3步即可完成任务

HDU-1207-汉诺塔II

妖精的绣舞 提交于 2020-02-03 20:49:33
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=1207 好题,四柱汉诺塔问题,两种解法,一种是直接用公式。 F(n)=min(2*F(n-r)+2^r-1),(1≤r≤n)。 通过这个方程我们能得到所有4柱汉诺塔 的步骤个数,同时也有人证明[1]了,对于 四柱汉诺塔,当r=(sqrt(8*n+1)-1)/2时, 能保证f(n)取得最小值F(n)=(n-(r^2-r+2)/2)*2^r+1。 所以算法的复杂度是F(n)=O(sqrt(2*n)*2^ sqrt(2*n))。 代码 #include<stdio.h> #include<stdlib.h> #include<math.h> int main(void) { int r,n; while(scanf("%d",&n)==1) { r=(sqrt(8*n+1)-1)/2; printf("%d\n",(n-(r*r-r+2)/2)*(int)pow(2,r)+1); } return 0; } 参数 0MS 256K 241 B 一种是 dp 设 A,B,C,D分别为四根柱子,开始圆盘在A柱子上,目的的柱子为C 柱,f[n]表示将n个盘子通过4根柱子移动到目的柱子C的最小的步数, a[i]表示 把 i个盘子通过 3根柱子移动到目的柱子C的最小步数,a[i]题目已经给出2^i-1.