uva 10254 the priest mathematician

本文探讨了使用四根针解决汉诺塔问题的优化策略,介绍了一位热爱数学的僧侣提出的解决方案,并通过Java实现算法来计算最少移动次数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Problem I

The Priest Mathematician

Input: standard input

Output: standard output

Time Limit: 10 seconds

 

The ancient folklore behind the "Towers of Hanoi" puzzle invented by E. Lucas in 1883 is quite well known to us. One more recent legend tells us that the Brahmin monks from Benares never believed that the world could vanish at the moment they finished to transfer the 64 discs from the needle on which they were to one of the other needles, and they decided to finish the task as soon as possible.

 

Fig: The Four Needle (Peg) Tower of Hanoi

 

One of the priests at the Benares temple (who loved the mathematics) assured their colleagues to achieve the transfer in the afternoon (the rhythm they had thought was a disc-per-second) by using an additional needle. They couldn't believe him, but he proposed them the following strategy:

 

-- First move the topmost discs (say the top k discs) to one of the spare needles.

 

-- Then use the standard three needles strategy to move the remaining n-k discs (for a general case with n discs) to their destination.

 

-- Finally, move the top k discs into their final destination using the four needles.

 

He calculated the value to k in order to minimize the number of movements and get a total of 18433 transfers, so they spent just 5 hours, 7 minutes and 13 seconds against the more than 500000 millions years without the additional needle (as they would have to do 2^64-1 disc transfers. Can you believe it?)

 

Try to follow the clever priest's strategy and calculate the number of transfer using four needles but according with the fixed and immutable laws of Brahma, which require that the priest on duty must not move more than one disc at a time and that he must place this disc on a needle so that there is no smaller disc below it. Of course, the main goal is to calculate the k that minimize the number of transfers (even thought it is not know for sure that this is always the optimal number of movements).

 

Input

The input file contains several lines of input. Each line contains a single integer N, which is the number of disks to be transferred. Here 0<=N<=10000. Input is terminated by end of file.

 

Output

For each line of input produce one line of output which indicates the number of movements required to transfer the Ndisks to the final needle.

 

Sample Input:

1

2

28

64

 

Sample Output:

1

3

769

18433


(World Finals Warm-up Contest, Problem Setter: Miguel Revilla)



关键的时候java是个好东西



import java.math.BigInteger;
import java.util.Scanner;

public class Main {
    public static void main (String [] args) {

        final int NMAX = 10010;

        BigInteger powOf2[] = new BigInteger[NMAX];
        powOf2[0] = new BigInteger ("1");
        for (int i=1; i<NMAX; ++i) {
            powOf2[i] = powOf2[i - 1].multiply (BigInteger.valueOf (2));
        }

        BigInteger f[] = new BigInteger[NMAX];

        f[0] = new BigInteger ("0");
        f[1] = new BigInteger ("1");

        for (int i=2; i<NMAX; ++i) {

            f[i] = f[i - 1].multiply (BigInteger.valueOf (2));
            f[i] = f[i].add (BigInteger.valueOf (1));

            for (int k=2; k<=i; ++k) {
                if (f[i].compareTo (powOf2[k].subtract (BigInteger.valueOf (1))) == -1) {
                    break;
                }
                BigInteger t = new BigInteger ("2");
                t = t.multiply (f[i - k]);
                t = t.add (powOf2[k]);
                t = t.subtract (BigInteger.valueOf (1));
                if (t.compareTo (f[i]) == -1) {
                    f[i] = t;
                }
            }
        }

        Scanner scanner = new Scanner (System.in);
        while (scanner.hasNext()) {
            int n = scanner.nextInt();
            System.out.println (f[n]);
        }
    }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值