题目大意:给你一个有$n$个盘子的汉诺塔状态$S$,问有多少种不同的操作方法,使得可以在$m$步以内到达状态$T$。$n,m\leqslant100$

题解:首先可以知道的是,一个状态最多可以转移到其他的$3$个状态,然后发现若$m\leqslant100$的话,每个柱子最多移动$7$个盘子,所以最多状态只有$3^{21}$次,这个数可能有点大,但是通过更严密的分析的话,最后状态数只有$10^5$级别,可以通过记忆化搜索通过。

卡点:妈啊,我怎么又把柱子上的顺序弄反了

C++ Code:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
const int mod = 998244353;
inline void reduce(int &x) { x += x >> 31 & mod; }int n, m, ans;
std::vector<int> S, T, v[3];
std::map<std::vector<int>, int> f[105];
int dfs(int x, std::vector<int> S, std::vector<int> *v) {if (f[x].count(S)) return f[x][S];if (!x) return 0;int &F = f[x][S];for (int i = 0; i < 3; ++i) if (v[i].size())for (int j = 0; j < 3; ++j)if (!v[j].size() || v[i].back() < v[j].back()) {S[v[i].back()] = j;v[j].push_back(v[i].back()), v[i].pop_back();reduce(F += dfs(x - 1, S, v) - mod);S[v[j].back()] = i;v[i].push_back(v[j].back()), v[j].pop_back();}return F;
}
int main() {std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);std::cin >> n >> m;for (int i = 0, x; i < n; ++i) std::cin >> x, S.push_back(--x);for (int i = 0, x; i < n; ++i) std::cin >> x, T.push_back(--x);for (int i = n - 1; ~i; --i) v[T[i]].push_back(i);f[0][S] = 1;for (int i = 0; i <= m; ++i) reduce(ans += dfs(i, T, v) - mod);std::cout << ans << '\n';return 0;
}

  

转载于:https://www.cnblogs.com/Memory-of-winter/p/11354382.html

[UOJ #167]【UR #11】元旦老人与汉诺塔相关推荐

  1. 汉诺塔实践python_汉诺塔的python 动画演示

    1.简介 古代有一座汉诺塔,塔内有3个座A.B.C,A座上有n个盘子,盘子大小不等,大的在下,小的在上,如图所示.有一个和尚想把这n个盘子从A座移到C座,但每次只能移动一个盘子,并且自移动过程中,3个 ...

  2. 函数(2)——4.兔子数列5.汉诺塔6.综合案例-RSA算法7.综合案例-体测成绩判定2021.11.16

    4.兔子数列(斐波那契数列) 一对兔子在出生两个月后,每个月能生出一对小兔子.现有一对刚出生的兔子,如果所有兔子都不死,那么一年后共有多少对兔子? 分析 n=1,兔子=1对: n=2,兔子=1对: n ...

  3. Ka的递归编程练习 Part4|Hanoi汉诺塔,双色汉诺塔的也有

    1 #include <stdio.h> 2 void hanoi(int s,char a,char b,char c) //a是出发盘,b是中途盘,c是结束盘 3 { 4 if(s== ...

  4. 两个经典递归问题:菲波那契数列 + 汉诺塔

    一.递归问题的处理步骤 1)抽象出递归公式:对实际问题进行部分穷举,抽象出递归关系(关键),并列出"递归表达式" 2)确定递归出口:找出递归调用终止点 二.菲波那契数列 实际问题: ...

  5. python递归详解+汉诺塔小案例_汉诺塔,python递归实现解法步骤

    def hanoi(n,x,y,z):#函数实现n个盘子在x,y,z,移动 if n==1: print(x, ' --> ', z) else: hanoi(n-1,x,z,y)#将n-1层个 ...

  6. 汉诺塔的实现 c++

    汉诺塔问题:假设有从左到右有三个名字分别为x,y,z的塔座, 在塔座x上有n各直径大小各不相同,按照直径从小到大编号为1,2,...n的圆盘.现在要求将x轴上的n个圆盘移动到塔座z上,并且按同样的顺序 ...

  7. 算法练习day15——190403(简介、求n!、汉诺塔、打印字符串的子序列、打印字符串的全排列、母牛生小牛、最小路径和、累加和是否达到给定值)

    1. 简介 动态规划是为了优化暴力尝试的. 2. 求n! 2.1 一般思路 public static long getFactorial2(int n) {long result = 1L;for ...

  8. 2_1_6 递归与分治策略(汉诺塔问题)

    汉诺塔问题是一个经典问题. 题意理解:有A,B,C三个柱子,将A柱子上的N个盘子(从小到大排列)移到C柱子上,每次只允许移动一个盘子,并且保证每个柱子上的盘子的排列都是从小到大. (图片源自百度图片) ...

  9. python 游戏 —— 汉诺塔(Hanoita)

    python 游戏 -- 汉诺塔(Hanoita) 一.汉诺塔问题 1. 问题来源 问题源于印度的一个古老传说,大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆 ...

最新文章

  1. js 获取图片url的Blob值并预览
  2. python PyQt5中文教程☞【第一节】PyQt5简介
  3. 理解git结构与简单操作(四)合并分支的方法与策略
  4. Linux 常用命令
  5. linux 向程序发送信号,Linux下的信号处理
  6. mysql常规使用(建立,增删改查,视图索引)
  7. 更改应用程序图标_在 Windows 10 version 1903 中查看应用程序是否支持 DPI 感知
  8. c# 使用GDAL处理大图
  9. 微信小程序怎么在wxml中插入多个图片_闲聊微信小程序开发框架(二)
  10. 学习GNU Make (1)(转)
  11. centos经常用到的一些文件
  12. matplotlib绘制李萨如图(一) 静态2D李萨如图
  13. 解决被卡巴斯基提示说KEY被列为黑名单
  14. js中undefined怎么判断
  15. 为什么pdf文件在一个计算机上能打开,拷贝到别的计算机上就打不开,显示文件已损坏?,pdf文件在电脑上打不开怎么办...
  16. C#迭代器的详细用法
  17. 十四、 ThinkPHP6_聚合.原生.子查询
  18. 生活简单案例,分析管理中的深奥道理
  19. oracle open hang 等待cursor: pin S wait on X---惜分飞
  20. tkinter窗口布局pack方法详解

热门文章

  1. 1036 跟奥巴马一起编程 (15 分)(c++)C++
  2. Git 分支 - 分支简介
  3. CF-1207 G.Indie Album(Trie上跑AC自动机)
  4. HDU 1729(石子)
  5. 轻松使用zstd来解压缩
  6. 记录 之 tensorflow中几个常用的函数:tf.unstack,tf.concat() 和 tf.stack() 等
  7. python常见的文件操作:打开、创建等
  8. GIMP - GNU 图像处理程序 用户手册
  9. HTML <!DOCTYPE> 标签
  10. 计算机程序设计语言教案,计算机程序设计(C语言)教案.doc