FOJ 1036 四塔问题
2014-01-31 09:48
190 查看
来源:http://acm.fzu.edu.cn/problem.php?pid=1036
概述:经典的汉诺塔使用到3个柱子ABC,不妨称为“三塔问题”,记把n个盘子从A移到C需要H(n)次操作。那么,四塔问题中4个柱子ABCD,记把n个盘子从A移到D需要F(n)次操作。请求解F(n),答案对1e4取余。
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
求解时,“『落』常笑鹰”和“原来我们都只是菜鸟”给予了很大的帮助,同时参阅了该篇文章:http://blog.csdn.net/wsqgwp/article/details/9164399。
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
理论分析
先理清三塔问题的思路。要完成H(n),就要先把n-1个盘子从A移到B(操作次数相当于把n-1个盘子从A移到C,即H(n-1)),接着把A中剩下那个,也是最大的盘子移到C,再把B中n-1个盘子移到C。从移动方法,可以看出递推公式H(n)=2H(n-1)+1。再根据H(1)=1,不难得出通项式
![](https://img-blog.csdn.net/20140131083912218?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY29kZTQxMDE=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
,下面为推导过程:
![](https://img-blog.csdn.net/20140131084941156?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY29kZTQxMDE=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
再来看四塔问题。对于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)次。所以有n种递推公式
![](https://img-blog.csdn.net/20140131085703609?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY29kZTQxMDE=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
在这n种递推方案中,我们要找出操作次数最小的最优解,故
![](https://img-blog.csdn.net/20140131090143109?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY29kZTQxMDE=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
从四塔问题,我们可以进一步得到n个盘子,m(m>3)个柱子的一般递推式(双递归)
![](https://img-blog.csdn.net/20140131090722265?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY29kZTQxMDE=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
此式的求解,用到两个性质
![](https://img-blog.csdn.net/20140131092438875?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY29kZTQxMDE=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
我的能力,目前也只能推导到这里了。但这些理论对于本题的求解并没有多大的帮助,一方面用这些递推式来求n最大为5万的4塔问题,显然整型数据会溢出;另一方面,对中间值取余,也会造成无法判断哪种组合才是真正的最小值。故下面也只能用“投机取巧”的方法,做出答案,并背住结论了。
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
实际求解
我们用理论分析出的F(n)公式,求出前几项值,来发现是否有数值递增的规律。如果有,那么通过每次递增值的方法做取余运算比用通项式还方便(因为通项式求解很可能还要写快速幂模板)。F(n)的求解可以列表手算,更方便的,也可以使用Excel。算出后,再算F(n)与F(n+1)的差,发现确实有规律性:
![](https://img-blog.csdn.net/20140131094007406?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY29kZTQxMDE=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
发现F(n)的递增规律为:一个2^0,两个2^1,三个2^2,四个2^3,接下来又是2^4,故猜想后续的规律——5个2^4,...,k+1个2^k,直到加到第n项。这个猜想从实践结果来看是正确的,但不会证明。
利用这规律,很容易实现编程求解。我的代码中用K代表当前加到第2^(K-1)部分,k代表加到2^(K-1)中第k项。把2^(K-1)值记为t,只要每次对t自乘2,并对1万取余即可。
概述:经典的汉诺塔使用到3个柱子ABC,不妨称为“三塔问题”,记把n个盘子从A移到C需要H(n)次操作。那么,四塔问题中4个柱子ABCD,记把n个盘子从A移到D需要F(n)次操作。请求解F(n),答案对1e4取余。
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
求解时,“『落』常笑鹰”和“原来我们都只是菜鸟”给予了很大的帮助,同时参阅了该篇文章:http://blog.csdn.net/wsqgwp/article/details/9164399。
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
理论分析
先理清三塔问题的思路。要完成H(n),就要先把n-1个盘子从A移到B(操作次数相当于把n-1个盘子从A移到C,即H(n-1)),接着把A中剩下那个,也是最大的盘子移到C,再把B中n-1个盘子移到C。从移动方法,可以看出递推公式H(n)=2H(n-1)+1。再根据H(1)=1,不难得出通项式
,下面为推导过程:
再来看四塔问题。对于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)次。所以有n种递推公式
在这n种递推方案中,我们要找出操作次数最小的最优解,故
从四塔问题,我们可以进一步得到n个盘子,m(m>3)个柱子的一般递推式(双递归)
此式的求解,用到两个性质
我的能力,目前也只能推导到这里了。但这些理论对于本题的求解并没有多大的帮助,一方面用这些递推式来求n最大为5万的4塔问题,显然整型数据会溢出;另一方面,对中间值取余,也会造成无法判断哪种组合才是真正的最小值。故下面也只能用“投机取巧”的方法,做出答案,并背住结论了。
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
实际求解
我们用理论分析出的F(n)公式,求出前几项值,来发现是否有数值递增的规律。如果有,那么通过每次递增值的方法做取余运算比用通项式还方便(因为通项式求解很可能还要写快速幂模板)。F(n)的求解可以列表手算,更方便的,也可以使用Excel。算出后,再算F(n)与F(n+1)的差,发现确实有规律性:
发现F(n)的递增规律为:一个2^0,两个2^1,三个2^2,四个2^3,接下来又是2^4,故猜想后续的规律——5个2^4,...,k+1个2^k,直到加到第n项。这个猜想从实践结果来看是正确的,但不会证明。
利用这规律,很容易实现编程求解。我的代码中用K代表当前加到第2^(K-1)部分,k代表加到2^(K-1)中第k项。把2^(K-1)值记为t,只要每次对t自乘2,并对1万取余即可。
#include <iostream> using namespace std; const int MAXN = 50001; void init(int F[]) { int k = 0, K = 1, t = 1; F[0] = 0; for (int i = 1; i < MAXN; i++) { F[i] = (F[i-1] + t) % 10000; k++; if (k == K) { K++; k = 0; t = t*2%10000; } } } int main() { int n, F[MAXN]; init(F); while (cin >> n) cout << F << endl; return 0; }
相关文章推荐
- FOJ 1036 四塔问题
- NYOJ 1036 非洲小孩 (区间选点问题)
- FOJ 1887 景区摊位安排问题
- FOJ 1205 小鼠迷宫问题
- FZU - 1036 - 四塔问题
- FZU FOJ 2030 括号问题【dp】||【暴搜+栈判断括号匹配】
- FOJ 1205 小鼠迷宫问题【BFS+dfs回溯查找路径】
- FOJ 1207 半数集问题
- C++信息学奥赛一本通题库1036A*B问题
- foj 1229 和谐短信问题
- Foj 1881 三角形问题
- FOJ 1036
- FZU 1036 四塔问题
- FZU - 1036 四塔问题【规律】
- FZU 1036 四塔问题
- Foj 1888 三角形问题II
- FOJ1205 小鼠迷宫问题 (BFD+递推)
- FOJ 1582 众数问题
- ACM: 动态规划题 poj 1036 问题简…
- foj 1416 飞机加油问题