zoukankan      html  css  js  c++  java
  • CF392B Tower of Hanoi

    题目链接

    Description

    三塔汉诺塔问题,给一个 (3 imes 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
    ", f[n][0][2]);
    	return 0;
    }
    
  • 相关阅读:
    ruby 二进制转十进制 Integer("0b101") = 5
    开始菜单和我的文档的我的图片及我的音乐变成 my pictrues 正常图标了
    ruby watir 莫名其妙的错误
    Excel SaveAS是去掉提示框
    apache && jboss安装
    ruby require include的区别
    ruby控制鼠标
    This error is raised because the column 'type' is reserved for storing the class in case of inheritance
    用正则表达式限制文本框只能输入数字,小数点,英文字母,汉字等各类代码
    ASP.NET 如何动态修改 Header 属性如添加 Meta 标签 keywords description!
  • 原文地址:https://www.cnblogs.com/dmoransky/p/12483477.html
Copyright © 2011-2022 走看看