题目链接:uva 10795 - A Different Task
题目大意:就是普通的汉诺塔问题,给出n,表示说有n个大小不同的碟子,然后再给出每个碟子的初始位置和目标位置,要求计算出最少的步数使得每个碟子都移动到它的目标位置。
解题思路:找到需要移动的最大碟子i,然后1~i-1个碟子需要移动到6 - now[i] - end[i],同样的需要让i - 1移动到6 - now[i] - end[i],需要让1~i - 2都移动到 6 - (6 - now[i] - end[i])- now[i - 1],所以很明显是递归求解,注意要将1~i - 2移动到i - 1上面。
然后进行完上述操作,从1~i-1都在同一个柱子上,可以从大到小将每个碟子还原到目标位置。
#include <stdio.h> #include <string.h> #include <math.h> #define ll long long const int N = 100; ll T[N]; int n, tmp, now[N], end[N]; void init() { memset(T, 0, sizeof(T)); T[0] = 1; for (int i = 1; i <= 63; i++) T[i] = T[i - 1] * 2; } void input() { memset(now, 0, sizeof(now)); memset(end, 0, sizeof(end)); for (int i = 1; i <= n; i++) scanf("%d", &now[i]); for (int i = 1; i <= n; i++) scanf("%d", &end[i]); } ll move(int d, int aid) { if (d == 0) return 0; if (now[d] == aid) return move(d - 1, aid); else return move(d - 1, 6 - now[d] - aid) + T[d - 1]; } ll solve() { int i; ll ans = 0; for (i = n; i; i--) { if (now[i] != end[i]) { tmp = 6 - now[i] - end[i]; ans += move(i - 1, tmp) + 1; i--; break; } } for (; i; i--) { if (end[i] != tmp) { tmp = 6 - end[i] - tmp; ans += T[i - 1]; } } return ans; } int main () { int cas = 1; init(); while (scanf("%d", &n) == 1 && n) { input(); printf("Case %d: %lld\n", cas++, solve() ); } return 0; }