uva 10795 - A Different Task(递归)

题目链接: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;
}


你可能感兴趣的:(uva 10795 - A Different Task(递归))