POJ 1920 Towers of Hanoi 数论

题目地址: http://poj.org/problem?id=1920


题目大意:给一个汉诺塔的摆放状态,要你求出现在这个状态下,到达最终的结果状态即从小到上方块递减。所用的移动次数最少。最终状态可以在任意一个铁杆下。

要求输出最终状态所在的铁杆号和最小移动步数。

可以反过来看,从最终状态到现在这个摆放状态所要求移动的最小步数



代码如下:(有详细注释)

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <queue>
using namespace std;

/*
freopen("input.txt",  "r", stdin);
freopen("output.txt", "w", stdout);
*/

const int N=100005;
const int II=1000000;
int xh[N],post[N],a[4];

int main()
{
    int i,j,n,t;
    xh[0]=1;
    xh[1]=2;
    while(cin>>n)
    {
        scanf("%d%d%d",&a[1],&a[2],&a[3]);
        for(i=1;i<=3;i++)
            for(j=1;j<=a[i];j++)
            {
                scanf("%d",&t);
                post[t]=i;
            }
        for(i=2;i<=n;i++)
        {
            xh[i]=(xh[i-1]<<1)%II;//这里的xh[i]比表示2^n
        }
        int temp=post[n-1],last=post[n];//last表示上一次盘子的位置,temp表示当前盘子的位置
        int s=0;
        for(i=n-1;i>0;i--,temp=post[i])
        {
            if(last!=temp)//如果上一个位置和当前位置不在一个棒子上面就进行
            {
                s=(s+xh[i-1])%II;//这个地方本来是加上i-1个汉罗塔移动的步数加一,但是因为上面的xh[i]表示的是2^i,减1加1抵消了
                last=6-last-post[i];//此时的上一次位置不在第i个位置也不在原先的那个位置,所以是6-last-post[i]
            }
        }
        printf("%d\n%d\n",post[n],s);//最大的那个盘子在那个棒子上那么最终移动在这个棒子的步数最少
    }
    return 0;
}


你可能感兴趣的:(POJ 1920 Towers of Hanoi 数论)