题目描述
四根柱子的汉诺塔问题,初始有nn个盘子在A柱,小盘子在上,大盘子在下。
要把所有盘子移到D柱上,一次只能移动一个盘子到另一个柱子上,任何时刻不能有大盘子放在小盘子上。
对于每个询问,输出最少的移动次数。
输入
第一行一个整数t(1≤t≤10)表示数据组数
接下来tt行,每行一个整数x(0≤x≤65535),表示每一组询问。
假设上一次询问的答案为yy,则此次询问的盘子数n=(x×y%16)+1,(规定第一组询问的y为10)
输出
对于每组数据,输出一行,一个整数,表示此次询问的最少移动次数
输入样例
2
5
10
输出样例
5
5
样例解释
对于第一组数据,y=10,x=5,n=(10×5%16)+1=3,答案为55。
对于第二组数据,y=5,x=10,n=(5×10%16)+1=3,答案为55。
题目链接:
https://buaacoding.cn/problem/2066/index
题目分析:
这是道四柱汉诺塔的题,在本菜鸡看到此题时隐隐约约觉得这道题我做不出来(滑稽)。
要做出本题,首先要清楚两点:
1. 三柱汉诺塔最少移动次数的结论
2. 四柱汉诺塔最少移动次数的策略
关于多柱汉诺塔的问题,大家在网上一搜都可以搜到,甚至还可以发现有论文专门研究多柱汉诺塔的最短路径问题,我在百度多柱汉诺塔的过程中发现一篇非常不错的推文:https://www.cnblogs.com/liudehao/p/4114414.html
看完推文后,你要做出本题,至少可以清楚上面两点的结论了。
1. 三柱汉诺塔最少移动次数的结论:2^n - 1
2. 四柱汉诺塔最少移动次数的策略:
(1)用4柱汉诺塔算法把A柱上部分的n- r个碟子通过C柱和D柱移到B柱上【F( n- r )步】。
(2)用3柱汉诺塔经典算法把A柱上剩余的r个碟子通过C柱移到D柱上【2^r-1步】。
(3)用4柱汉诺塔算法把B柱上的n-r个碟子通过A柱和C柱移到D柱上【F(n-r)步】。
(4)依据上边规则求出所有r(1≤r≤n)情况下步数f(n),取最小值得最终解。
#include<stdio.h> int min(int x, int y){ return x < y ? x : y; } int hanoi3(int n){ return (1 << n) - 1; // 三柱汉诺塔最短移动次数的结论 } int hanoi4(int n){ if(n == 0) return 0; if(n == 1) return 1; int ans = 0x7fffffff; // 初始化为int范围的最大值 int i; for(i = 1; i <= n; i++) ans = min(ans, 2 * hanoi4(n - i) + hanoi3(i)); return ans; } int main(){ int t, i, ans; int x, y = 10, n; scanf("%d", &t); while(t--){ scanf("%d", &x); n = (x * y % 16) + 1; ans = hanoi4(n); printf("%d ", ans); y = ans; } return 0; }