HANOI
the easiest one
题目大意:
用最少的次数,把那三个圆柱给移到指定的C柱上,然后把次数输出(要最少的)
找规律
首先来说一下等差序列:
一阶:形如1,3,5,7,9……
高级:二阶:1,4,9,16,25……
1+2+3+4+……n=n(n+1)/2
12+22+32+42+……+n2=n(n+1)(2n+1)/6
1
×
\times
× 2+2
×
\times
× 3+……+n
×
\times
× (n+1)=1/3(2
×
\times
× 3
×
\times
× 4 -1
×
\times
× 2
×
\times
× 3)+……=1/3n(n+1)(n+2)
此题:首先,这道题的解题过程可以分成三部分:
一、将前2*(N-1)个盘子移到B柱;(不然你最后两个盘子移不出来);
二、将最后两个盘子移到C柱;
三、再将B柱上的2*(N-1)个盘子移到C柱;
然后,我们可以开一个数组F[N]表示将2*N个盘子从一个柱子移到另一个柱子所用的最少步数。
所以:f(n)=2^(a+1)-2
注意:一定要高精
代码:a=int(input()) print(2**(a+1)-2)
Python
more difficult
给你一个数m,求第m步是编号为几的盘子从哪到哪(64<m<100)
void print(int n, char A, char B, char C) {
if (n == 0) return;
print(n - 1, A, C, B);
printf("%d %c %c", n, A, C);
print(n - 1, B, A, C);
}
调用print(n, ‘A’, ‘B’, ‘C’)
那你考虑
printK(int n, int k, char A, char B, char C)
表示输出第k步
那么考虑第k步是在
print(n - 1, A, C, B);
printf("%d %c %c", n, A, C);
print(n - 1, B, A, C);
这三行里哪一个
如果k <= 2(n-1) - 1
那么就是第一行里,递归调用
printK(n - 1, k, A, C, B);
如果k = 2(n-1)那么就正好在中间那一行,因此输出
printf("%d %c %c", n, A, C);
否则的话相当于先把k减去2^(n-1)然后往后面递归
也就是调用
printK(n - 1, k - (1 << (n - 1)), A, C, B);
那么相当于把k写成二进制
从第n-1位往右扫到第0位
如果扫到一个0,说明这一步是第一种情况,递归下去相当于swap(B, C)
如果扫到一个1,那么是第三种
这时候相当于swap(A,B)
如果这个1正好是二进制最后一个1,那就说明剩下的是一个2i
这时候print(i+1, A, C)
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
int n,ans=0;
unsigned long long m;
void dfs(int n,unsigned long long m,char a,char b,char c){
unsigned long long k=1ull<<(n-1);
if(m==k){
printf("move %d from %c to %c",n,a,c);
return ;
}
else if(m<k)dfs(n-1,m,a,c,b);
else if(m>k)dfs(n-1,m-k,b,a,c);
}
int main(){
scanf("%d%u",&n,&m);
dfs(n,m,'A','B','C');
return 0;
}
四塔问题
再来看四塔问题。对于F(n),我们可以先把A中的j(0 ≤ j < n)个盘子移到B,需要F(j)次操作,然后在柱子ACD中,完成剩下的n-j个盘子操作——把A中n-j个盘子,利用C,移动到D,这等价于三塔问题,所以操作次数为H(n-j),再把B中的j个盘子移到D,操作F(j)次。