P - Towers of Hanoi POJ - 1920

P - Towers of Hanoi

 POJ - 1920 

Surely you have already come across the Towers of Hanoi problem: Wooden disks of different sizes are stacked on three pegs, and initially, all disks are stacked on the same peg sorted by size, with the largest disk at the bottom. The objective is to transfer the entire tower to one of the other pegs, moving only one disk at a time and never putting a larger disk onto a smaller one. 
According to an old myth, the monks at an ancient Tibetian monastery have been trying to solve an especially large instance of this problem with 47 disks for thousands of years. Since this requires at least 2 47 - 1 moves and the monks started out without a strategy, they messed it all up while still following the rules. Now they would like to have the disks stacked up neatly on any arbitrary peg using the minimum number of moves. But they all took a vow which forbids them to move the disks contrary to the rules. They want to know on which peg they should best stack the disks, and the minimum number of moves needed. 
Write a program that solves this problem for the monks. Your program should also be able to handle any number N (0 < N <= 100 000) of disks. The numbers involved in the computation can become quite large. Because of that, the monks are only interested in the number of moves modulo 1 000 000. 
Example 
The following example can be solved in four moves. 

 

Input

The first line of the input file hanoi.in consists of the number N (N <= 100000) of disks. The second line consists of three integers s1, s2, s3 with 0 <= s1, s2, s3 <= N and s1+s2+s3 = N, the number of disks on each of the three pegs. Lines three to five each contain the sizes of the disks for one peg. More precisely: 
The (i + 2)-th line of the input file consists of integer numbers m i,1 . . .m i,siwith 1 <= m i,j <= N, the sizes of the disks on peg i. The disks are given from bottom to top, thus m i,1 > m i,2 > . . . > m i,si . 
Note that an empty stack is given by an empty line. The set of N disks have different sizes. All numbers are separated by a single space.

Output

The first line of the output file hanoi.out consists of the number d in {1, 2, 3} of the peg onto which the disks can be stacked using the minimum number of moves. The second line consists of the number M of required moves modulo 1 000 000.

Sample Input

7
2 1 4
2 1
3
7 6 5 4

Sample Output

3
4

题意:开始各个碟子分布在三个钉子上,问把这些碟子移到一个钉子上的最小移动步数,及最终移到哪个钉子上。

思路:逆推,那么最大那个碟子是不必要移动的,逆推如下:开始全部钉子在a[n]号钉子上,第n个碟子是固定的,然后
从大到小考虑碟子的移到,这样考虑是因为较大碟子确认后,较小碟子的移动不受到较大碟子的影响,那么查看第n-1个碟子最终要到达的钉子,如果第n-1个碟子最后要到达的钉子号=a[n-1]不在不在当前的钉子堆中(a[n]),那么需要把第n-1个碟子上面的
n-2个碟子暂时移到6-a[n]-a[n-1]号钉子(三个钉子的号数的和为6)上,而移动n-2个碟子到另外的钉子上的移动次数为(pow(2,n-2)-1)次,剩余的碟子又是一个规模为n-2的碟子的问题;

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<iostream>
#include<map>
#include<vector>
using namespace std;
#define N 100010
#define nmax 15100
#define inf 0x3f3f3f3f
const int mod=1000000;
int p[N],a[N],sum[4];
int main()
{
    int n,x;
    while(scanf("%d",&n)!=EOF)
    {
        for(int i=1; i<=3; i++)
            scanf("%d",&sum[i]);
        for(int i=1; i<=3; i++)
        {
            for(int j=1; j<=sum[i]; j++)
            {
                scanf("%d",&x);
                a[x]=i;//要求第x个碟子所在钉子号为i
            }
        }
        p[0]=1;
        p[1]=2;
        for(int i=2; i<=n; i++)
            p[i]=(p[i-1]*2)%mod;
      /*now为所有没有确认位置的碟子的当前位置,
      每次移动号一个碟子后,剩余还没判断的碟子
      都在一个钉子上
      */
        int now=a[n],ans=0;  
        for(int i=n-1; i>0; i--)
        {
            if(now!=a[i])
            {
                ans=(ans+p[i-1])%mod;//ans=(ans+p[i-1]-1+1)%mod
                now=6-now-a[i];  //剩余碟子集体移到另外第3个钉子上
            }
        }
        printf("%d\n%d\n",a[n],ans);
    }
    return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值