奇怪的汉诺塔

96. 奇怪的汉诺塔 - AcWing题库

题意

汉诺塔问题,条件如下:

1、这里有 A、B、C 和 D 四座塔。

2、这里有 n 个圆盘,n 的数量是恒定的。

3、每个圆盘的尺寸都不相同。

4、所有的圆盘在开始时都堆叠在塔 A 上,且圆盘尺寸从塔顶到塔底逐渐增大。

5、我们需要将所有的圆盘都从塔 A 转移到塔 D 上。

6、每次可以移动一个圆盘,当塔为空塔或者塔顶圆盘尺寸大于被移动圆盘时,可将圆盘移至这座塔上。

请你求出将所有圆盘从塔 A 移动到塔 D,所需的最小移动次数是多少。

19_acbb764014-河内塔
汉诺塔参考模型

思路

首先我们要明确这题在问什么,用一句话概括上面的题意:将n层汉诺塔,通过两根柱子的辅助,移动到第四根柱子上

g[n] 为 n 层汉诺塔按照题意需要移动的最小步数,g[n] 可以怎么求呢?

先取最上面的 i 层,通过 C、D 两个柱子 移动到 B 柱上,再把剩下的 n - i 层 通过 C 柱 移动到 D 柱,最后把 B 柱上的 i 层 通过 A、C两个柱子移动到 D 柱,每个过程的最小值加在一起就是最小步数。

上述过程中,有两个过程为 借助两个柱子,从一个柱子移动到另一个柱子 这即为我们要求的 g 数组,还有一个过程为 借助一个柱子,从一个柱子移动到另一个柱子 这就是我们熟悉的 三柱汉诺塔问题。

对于每一个 n 枚举 i 找到最小值 即为答案

代码
#include<bits/stdc++.h>
// #define int long long
#define INF 0x3f3f3f3f
#define mod 1000000007
#define MOD 998244353
#define rep(i, st, ed) for (int (i) = (st); (i) <= (ed);++(i))
#define pre(i, ed, st) for (int (i) = (ed); (i) >= (st);--(i))

using namespace std;

typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
template<typename T> inline T gcd(T a, T b) { return b ? gcd(b, a % b) : a; }
template<typename T> inline T lowbit(T x) { return x & -x; }

const int N = 1e3 + 10;
int f[20], g[20];

int n = 12;
void solve() {
	f[1] = 1;
	for (int i = 2; i <= n; ++i) {
		f[i] = 2 * f[i - 1] + 1;
	}

	memset(g, 0x3f, sizeof g);
	g[1] = 1;
	for (int i = 1; i <= n; ++i) {
		for (int j = 0; j <= i; ++j) {
			g[i] = min(g[i], 2 * g[j] + f[i - j]);
		}
	}

	for (int i = 1; i <= 12; ++i)printf("%d\n", g[i]);
}

signed main() {
	// int t; cin >> t;
	// while (t--)
		solve();

	return 0;
}

in() {
// int t; cin >> t;
// while (t–)
solve();

return 0;

}




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zzqwtc

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值