UVA - 10795 A Different Task

题意:给定一个初始状态和目标状,求从初始状态到目标状态最少要多少步,规则跟汗诺塔是一样的

思路:看了大白的是:先找到需要移动的最大的K,比它大的显然是不需要移动的可以不用考虑,那么可以考虑在将第K个盘子移动的前一步的状态一定是:K在第一根柱子,比大小的依次排在第3根柱子,将这个状态定位参考状态,那么初始状态到这个参考状态加上目标状态到参考状态的步数再+1就是答案了,那么在移动的过程中,如果当前需要移动的N在目标状态那么就不需要移动,就是等于前N-1的步数,否则就是要把前N-1个先移动到另一根暂放,而这个过程满足经典的汉诺塔问题,步数就是2^(N-1)-1,还要再加上移动第N个的1

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 70;

int n,start[MAXN],finish[MAXN];

long long f(int *p,int i,int final){
    if (i == 0)    
        return 0;
    if (p[i] == final)
        return f(p,i-1,final);
    return f(p,i-1,6-p[i]-final) + (1LL<<(i-1));
}

int main(){
    int cas = 0;
    while (scanf("%d",&n) != EOF){
        for (int i = 1; i <= n; i++)
            scanf("%d",&start[i]);
        for (int i = 1; i <= n; i++)
            scanf("%d",&finish[i]);
        int k = n;
        while (k >= 1 && start[k] == finish[k]) k--;
        long long ans = 0;
        if (k >= 1){
            int other = 6 - start[k] - finish[k];
            ans = f(start,k-1,other) + f(finish,k-1,other) + 1;
        }
        printf("Case %d: %lld\n",++cas,ans);
    }
    return 0;
}



你可能感兴趣的:(UVA - 10795 A Different Task)