题目链接

Description

三塔汉诺塔问题,给一个 \(3 \times 3\) 的矩阵 \(t\),\(t_{i, j}\) 表示从 \(i\) 塔移动一个盘子到 \(j\) 塔的花费。

初始状态 \(n\) 个盘子都在第一个盘子,要求将所有的移到第三个盘子,求最小花费。

Solution

显然可以间接移动,花费有可能更优,先用 Floyd 算法算出从 \(i\) 间接 / 直接移动到 \(j\) 的最小花费,设 \(d_{i,j}\) 表示从 \(i\) 到 \(j\) 的最小花费。

显然无后效性,考虑 \(dp\)。

状态设计

设 \(f_{i,a,b}\) 表示将 \(i\) 个盘子从 \(a\) 移动到 \(b\) 的最小花费。

初始状态

\(f_{1, a, b} = d_{a,b}\) 其余为正无穷

状态转移

不妨设另外一个盘子为 \(c\)。

先把 \(n\) 个盘子看做两个整体:第 \(n\) 个盘子和 \(n - 1\) 个盘子,这样可以 DP 了。

通过观察发现有两个可能成为最优的转移方式:

  • 将 \(n - 1\) 个盘子 \(a \Rightarrow c\),第 \(n\) 个盘子 \(a \Rightarrow b\),然后再把 \(n - 1\) 个盘子 \(c \Rightarrow b\)。
  • \(n - 1\) 个盘子 \(a \Rightarrow b\),第 \(n\) 个盘子 \(a \Rightarrow c\),\(n - 1\) 个盘子 \(b \Rightarrow a\),第 \(n\) 个盘子 \(c \Rightarrow b\),\(n - 1\) 个盘子 \(a \Rightarrow b\)。

其他的转移一定是这两种 + 反复横跳形成的。

将上面的方式翻译一下,即:

  • \(f_{i, a, b} \gets f_{i - 1, a,c} + t_{a,b} + f_{i - 1, c, b}\)

  • \(f_{i, a, b} \gets f_{i - 1, a,b} + t_{a,c} + f_{i - 1, b, a} + t_{c,b} + f_{i - 1, a, b}\)

值得注意的是这里不能用 \(d\),因为其他盘子不是空的,不能作为间接量。

时间复杂度

\(O(N)\)

Tips

注意开 long long !

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std; const int N = 45; typedef long long LL; int t[3][3], g[3][3], n;
LL f[N][3][3]; int main() {
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++) scanf("%d", &t[i][j]), g[i][j] = t[i][j];
scanf("%d", &n);
for (int k = 0; k < 3; k++)
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
t[i][j] = min(t[i][j], t[i][k] + t[k][j]);
memset(f, 0x3f, sizeof f);
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
f[1][i][j] = t[i][j]; for (int i = 2; i <= n; i++) {
for (int a = 0; a < 3; a++) {
for (int b = 0; b < 3; b++) {
if (a == b) continue;
int c = 3 - a - b;
f[i][a][b] = min(f[i - 1][a][c] + g[a][b] + f[i - 1][c][b], f[i - 1][a][b] + g[a][c] + f[i - 1][b][a] + g[c][b] + f[i - 1][a][b]);
}
}
}
printf("%lld\n", f[n][0][2]);
return 0;
}

CF392B Tower of Hanoi的更多相关文章

  1. poj 3601 Tower of Hanoi

    Tower of Hanoi Time Limit: 1000MS   Memory Limit: 131072K Total Submissions: 1853   Accepted: 635 De ...

  2. python递归三战:Sierpinski Triangle、Tower of Hanoi、Maze Exploring

    本文已做成视频教程投稿b站(视频版相对文本版有一些改进),点击观看视频教程 本文主要通过三个实例来帮助大家理解递归(其展示动画已上传B站): 谢尔宾斯基三角形(Sierpinski Triangle) ...

  3. 汉诺塔问题(The Tower of Hanoi)的递归算法与非递归算法

    非递归算法: 根据圆盘的数量确定柱子的排放顺序: 若n为偶数,按顺时针方向依次摆放 A B C: 若n为奇数,按顺时针方向依次摆放 A C B. 然后进行如下操作: (1)按顺时针方向把圆盘1从现在的 ...

  4. Tower of Hanoi问题

    [问题描述] 有A, B, C三个塔座,A上套有n个直径不同的圆 盘,按直径从小到大叠放,形如宝塔,编号1, 2, 3 … n. 要求将n个圆盘从A移到C,叠放顺序不变,移动过程中遵循 下列原则: w ...

  5. [POJ1958][Strange Tower of Hanoi]

    题目描述 求解 \(n\) 个盘子 \(4\) 座塔的 Hanoi 问题最少需要多少步 问题分析 考虑 \(3\) 座塔的 Hanoi 问题,记 \(f[i]\) 表示最少需要多少步, 则 \(f[i ...

  6. One usage of recurison: the tower of Hanoi

    Statements: This blog was written by me, but most of content  is quoted from book[Data Structure wit ...

  7. 汉诺塔 Tower of Hanoi

    假设柱子标为A,B.C.要由A搬至C,在仅仅有一个盘子时,就将它直接搬至C:当有两个盘子,就将B作为辅助柱.假设盘数超过2个.将第二个下面的盘子遮起来,就非常easy了.每次处理两个盘子,也就是:A- ...

  8. codeforces 392B Tower of Hanoi

    把前n个碟子从第一个塔移动到第三个塔有两种方法: 1.把前n-1个移动到第二个塔,把第n个移动到第三个塔,然后把前n-1个从第二个移动到第三个: 2.把前n-1个移动到第三个塔,把第n个移动到第二个塔 ...

  9. codeforces392B

    CF392B Tower of Hanoi 题意翻译 河内塔是一个众所周知的数学难题.它由三根杆和一些可以滑动到任何杆上的不同尺寸的圆盘组成.难题从一个整齐的杆中开始,按照尺寸从小到大的顺序排列,最小 ...

随机推荐

  1. tcp syn-synack-ack 服务端接收ack

    TCP 服务端 接收到ack tcp_v4_rcv() -> tcp_v4_do_rcv() -> tcp_v4_hnd_req() + tcp_child_process()tcp_v4 ...

  2. Best Time to Buy and Sell Stock I II III IV

    一.Best Time to Buy and Sell Stock I Say you have an array for which the ith element is the price of ...

  3. OpenCV之图像归一化(normalize)

    什么图像归一化 通俗地讲就是将矩阵的值通过某种方式变到某一个区间内 图像归一化的作用 目前能理解的就是归一化到某个区间便于处理,希望高人可以指点 opencv文档中的介绍 C++: void norm ...

  4. 使用@Validated校验数据(除数据库做辅助)

    一.controller层 /** * 使用@Validated来进行校验 * @author HuangJingNa * @date 2019年12月23日 下午6:02:20 * * @param ...

  5. Python_案例_斐波那契数

    方法一: 1 #!/usr/bin/python3 2 3 # Fibonacci series: 斐波纳契数列 4 # 两个元素的总和确定了下一个数 5 a, b = 0, 1 6 while b ...

  6. Python_DOM

    Dom简介:Js通过标签筛选让html多文件联动 1.找到标签 获取单个元素 docum ent.getElemrntByID('i1') 获取多个元素(列表)document.getElemrnts ...

  7. Apache Shiro 反序列化漏洞复现(CVE-2016-4437)

    漏洞描述 Apache Shiro是一个Java安全框架,执行身份验证.授权.密码和会话管理.只要rememberMe的AES加密密钥泄露,无论shiro是什么版本都会导致反序列化漏洞. 漏洞原理 A ...

  8. jdk的切换

    1.下载安装新版本的jdk 2.使用该命令,添加新版jdk alternatives --install /usr/bin/java java /opt/jdk1.8.0_144/bin/java 2 ...

  9. Camtasia的标记使用方法

    相信大家都想过学习或者尝试过编辑视频,可能曾经也下载使用过微课录制软件Camtasia(win),或许现在也还在使用.小编现在也经常使用Camtasia录屏编辑视频,在编辑的过程中,总是会不小心在轨道 ...

  10. 对KVC和KVO的理解

    html { overflow-x: initial !important } :root { --bg-color: #ffffff; --text-color: #333333; --select ...