10 UVA10795 A Different Task & 新汉诺塔问题 题解

A Different Task

题面

给定一个汉诺塔的初始局面以及目标局面,求将初始局面化为目标局面至少需要多少步?

\(1 \le T \le 100, 1 \le n \le 60\)

题解

这道题思想挺不错的。

我们不难想到先看大盘如何移动,因为我们传统汉诺塔中也是考虑最后一个大盘如何移动,因为如果大盘放到了相应的位置,小盘移动的时候不受影响。

我们找到第一个初始位置和目标位置不同的盘子,设为第 \(k\) 个盘子,那么所有 \(>k\) 的盘子都不需要管了,因为它们已经在对应位置,并且不会影响我们的后续移动,我们忽略这些不需要管的盘子。

我们设初始位置数组为 \(start\),目标位置数组为 \(end\)

要将 \(k\)\(start[k]\) 移动到 \(end[k]\),设 \(other = 6 - start[k] - end[k]\)

满足 \(k\) 上面没有盘子,并且 \(end[k]\) 上没有盘子(忽略 \(>k\) 的盘子后),这也就等价于将 \(1 \sim k - 1\) 盘子从 \(start\) 局面移动到 \(other\) 上,然后将 \(k\) 移动到 \(end[k]\),再将 \(other\) 上的 \(1 \sim k - 1\) 移动到 \(end\) 局面。

我们设 \(f(p, x, final)\) 表示当前局面为 \(p\),将 \(1 \sim x\) 移动到 \(final\) 这个柱子的最小代价。

那么我们上面的计算过程可以写成:\(f(start, k - 1, other) + 1 + f(end, k - 1, other)\)

由于对称性,所以我们最后一步可以写成 \(f(end, k - 1, other)\),相当于将我们原来的过程倒着搞。

关于 \(f(p, x, final)\) 的计算:

边界 \(f(p, 0, final) = 0\)

如果 \(p[x] = final\),那么我们返回 \(f(p, x - 1, final)\)

否则返回 \(f(p, x - 1, 6 - p[x] - final) + 1 + (2^{x - 1} - 1)\),表示先将前 \(x - 1\) 个盘子移动到中转盘,然后将 \(x\) 放到 \(final\),最后再将前 \(x - 1\) 个盘子从中转盘移动到 \(final\),最后一步可以使用公式计算 \(g(n) = 2^n - 1\)

单次时间复杂度 \(O(n)\),总时间复杂度 \(O(Tn)\)

code

#include <bits/stdc++.h>

using namespace std;

namespace michaele {
	
	#define rep(i, s, t) for (int i = s; i <= t; i ++)
	#define irep(i, s, t) for (int i = s; i >= t; i --)
	typedef pair <int, int> pii;
	typedef long long ll;

	const int N = 70;

	int n;
	int start[N], end[N];

	ll dfs (int *p, int x, int final) {
		if (x == 0) return 0;
		if (p[x] == final) return dfs (p, x - 1, final);
		int other = 6 - p[x] - final;
		return dfs (p, x - 1, other) + (1ll << x - 1);
	}

	void solve () {
		int cntC = 0;
		while (cin >> n) {
			if (!n) break;
			rep (i, 1, n) cin >> start[i];
			rep (i, 1, n) cin >> end[i];
			int k = n;
			while (k && start[k] == end[k]) k --;
			ll ans = 0;
			if (k >= 1) {
				int other = 6 - start[k] - end[k];
				ans = dfs (start, k - 1, other) + dfs (end, k - 1, other) + 1;
			}
			printf ("Case %d: %lld\n", ++ cntC, ans);
		}
	}
}

int main () {

	michaele :: solve ();

	return 0;
}
posted @ 2025-11-03 15:35  michaele  阅读(9)  评论(0)    收藏  举报