QwQ太懒了,题目直接复制uoj的了

QwQ这个题可以说是十分玄学的一道题了

首先可以暴搜,就是\(dfs\)然后模拟每个过程是哪个柱子向哪个柱子移动

不多解释了,不过实现起来还是有一点点难度的

直接上代码吧

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue> using namespace std; inline int read()
{
int x=0,f=1;char ch=getchar();
while (!isdigit(ch)) {if (ch=='-') f=-1;ch=getchar();}
while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
} const int maxn = 110;
const int mod = 998244353; int a[maxn][maxn];
int bel[maxn];
int top[maxn];
int st[maxn];
int ed[maxn];
int num;
int n,m;
int ans; void to(int i,int j)
{
int x = a[i][top[i]];
if (ed[x]==i) num--;
a[i][top[i]--]=0;
a[j][++top[j]]=x;
if (ed[x]==j) num++;
} void dfs(int tmp)
{
//for (int i=1;i<=3;i++)
//{
// cout<<"第"<<i<<"个柱子: " ;
// for (int j=1;j<=top[i];j++)
// {
// cout<<a[i][j]<<" ";
// }
// cout<<endl;
//}
//cout<<"---------------------"<<endl;
if (num==n){ans++;if (ans>mod) ans-=mod;};
if (tmp==m+1) return;
for (int i=1;i<=3;i++)
{
for (int j=1;j<=3;j++)
{
if (i==j) continue;
if (top[i]<=0) continue;
if (a[i][top[i]]>a[j][top[j]] && top[j]>0) continue;
to(i,j);
dfs(tmp+1);
to(j,i);
}
}
} int main()
{
scanf("%d%d",&n,&m);
if (m>14) {
cout<<292996445%mod<<endl;
return 0;
}
for (int i=1;i<=n;i++) st[i]=read();
for (int i=1;i<=n;i++) ed[i]=read();
for (int i=1;i<=n;i++) if (st[i]==ed[i]) num++;
for (int i=n;i>=1;i--) a[st[i]][++top[st[i]]]=i;
//cout<<num<<endl;
dfs(1);
cout<<ans;
return 0;
}

经过仔(guan)细(kan)思(ti)考(jie)不难发现,这个题,有用的状态只有\(3^n\)种,我们可以令\(f[i][j]\)表示当前的操作步数是\(i\),各个盘子的状态是\(j\)的合法移动方案数

然后记忆化一下!竟然过了!!!

具体的复杂度分析在这

不过这个题还是有很多记得学习的地方!

1.模拟移动的过程只需要考虑柱子,而不是盘子

2.记录状态的时候可以用vector+map来实现 很方便

上代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map> using namespace std; inline int read()
{
int x=0,f=1;char ch=getchar();
while (!isdigit(ch)) {if (ch=='-') f=-1;ch=getchar();}
while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
} const int mod = 998244353;
const int maxn = 110; map<vector<int>,int> f[maxn],g[maxn];
int a[maxn],b[maxn];
int n,m;
vector<int> v,vv;
int ans=0; int dfs(vector<int> x,int num)
{
int cnt=0,top[10];
if (num<0) return 0;
memset(top,127/3,sizeof(top));
if (g[num][x]) return f[num][x];
g[num][x]=1;
x.resize(n);
// for (int i=n-1;i>=0;i--) cout<<x[i]<<endl<<endl;
for (int i=n-1;i>=0;i--) top[x[i]]=i;
for (int i=1;i<=3;i++)
for (int j=1;j<=3;j++)
{
if (i==j) continue;
if (top[i]<top[j])
{
x[top[i]]=j;
cnt=(cnt+dfs(x,num-1))%mod;
x[top[i]]=i;
}
}
f[num][x]=cnt;
return f[num][x];
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++) a[i]=read(),v.push_back(a[i]);
for (int i=1;i<=n;i++) b[i]=read();
f[0][v]=1;
g[0][v]=1;
v.clear();
for (int i=1;i<=n;i++) vv.push_back(b[i]);
for (int i=0;i<=m;i++)
{
ans=(ans+dfs(vv,i))%mod;
}
cout<<ans;
return 0;
}

uoj167 元旦老人与汉诺塔(记忆化搜索)的更多相关文章

  1. [UOJ #167]【UR #11】元旦老人与汉诺塔

    题目大意:给你一个有$n$个盘子的汉诺塔状态$S$,问有多少种不同的操作方法,使得可以在$m$步以内到达状态$T$.$n,m\leqslant100$ 题解:首先可以知道的是,一个状态最多可以转移到其 ...

  2. UR11 A.元旦老人与汉诺塔

    题目:http://uoj.ac/contest/23/problem/167 如果我们拿个map来存状态的话.设当前状态是v,下一个状态是s.有f[i+1][s]+=f[i][v]. 初始f[0][ ...

  3. 奇妙的算法【4】-汉诺塔&哈夫曼编码

    1,汉诺塔问题[还是看了源码才记起来的,记忆逐渐清晰] 汉诺塔:汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具.大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着6 ...

  4. 算法笔记_013:汉诺塔问题(Java递归法和非递归法)

    目录 1 问题描述 2 解决方案  2.1 递归法 2.2 非递归法 1 问题描述 Simulate the movement of the Towers of Hanoi Puzzle; Bonus ...

  5. C#递归解决汉诺塔问题(Hanoi)

    using System;using System.Collections.Generic;using System.Linq;using System.Text; namespace MyExamp ...

  6. 数据结构0103汉诺塔&八皇后

    主要是从汉诺塔及八皇后问题体会递归算法. 汉诺塔: #include <stdio.h> void move(int n, char x,char y, char z){ if(1==n) ...

  7. Conquer and Divide经典例子之汉诺塔问题

    递归是许多经典算法的backbone, 是一种常用的高效的编程策略.简单的几行代码就能把一团遭的问题迎刃而解.这篇博客主要通过解决汉诺塔问题来理解递归的精髓. 汉诺塔问题简介: 在印度,有这么一个古老 ...

  8. 几年前做家教写的C教程(之四专讲了指针与汉诺塔问题)

    C语言学习宝典(4) 指针:可以有效的表示复杂的数据结构,能动态的分配动态空间,方便的使用字符串,有效的使用数组,能直接处理内存单元 不掌握指针就没有掌握C语言的精华 地址:系统为每一个变量分配一个内 ...

  9. python实现汉诺塔

    经典递归算法汉诺塔分析: 当A柱子只有1个盘子,直接A --> C 当A柱子上有3个盘子,A上第一个盘子 --> B, A上最后一个盘子 --> C, B上所有盘子(1个) --&g ...

随机推荐

  1. mybaits源码分析--类型转换模块(三)

    一.类型转换模块 String sql = "SELECT id,user_name,real_name,password,age,d_id from t_user where id = ? ...

  2. 多源最短路径,一文搞懂Floyd算法

    前言 在图论中,在寻路最短路径中除了Dijkstra算法以外,还有Floyd算法也是非常经典,然而两种算法还是有区别的,Floyd主要计算多源最短路径. 在单源正权值最短路径,我们会用Dijkstra ...

  3. PHP小数点后保留位数并四舍五入

    ceil() 函数向上舍入为最接近的整数,进一(k>0).ceil(0.60) --> 1ceil(0.40) --> 1ceil(5) --> 5ceil(5.1) --&g ...

  4. 搭建本地yum源出现:mount: 在 /dev/sr0 上找不到媒体

    2021-07-27 在练习环境搭建时,因为是离线环境,故先搭建本地yum源,但是出现了一个往常没有的问题:mount: 在 /dev/sr0 上找不到媒体,参考其他博主的文章得到解决方法. 排查问题 ...

  5. 云原生 AI 前沿:Kubeflow Training Operator 统一云上 AI 训练

    分布式训练与 Kubeflow 当开发者想要讲深度学习的分布式训练搬上 Kubernetes 集群时,首先想到的往往就是 Kubeflow 社区中形形色色的 operators,如 tf-operat ...

  6. Docker详解(一)——

    Docker详解 https://www.cnblogs.com/antLaddie/p/14276726.html

  7. Python - 面向对象编程 - __str__()

    为什么要讲 __str__ 在 Python 中,直接 print 一个实例对象,默认是输出这个对象由哪个类创建的对象,以及在内存中的地址(十六进制表示) 假设在开发调试过程中,希望使用 print ...

  8. Python - 面向对象编程 - __repr__()

    为什么要讲 __repr__ 在 Python 中,直接 print 一个实例对象,默认是输出这个对象由哪个类创建的对象,以及在内存中的地址(十六进制表示) 假设在开发调试过程中,希望使用 print ...

  9. Apache网页优化

    目录: 一.Apache网页优化概述 二.网页压缩 三.网页缓存 四.隐藏版本信息 五.Apache防盗链 一.Apache网页优化概述 在企业中,部署Apache后只采用默认的配置参数,会引发网站很 ...

  10. git config 选项

    git config  --global -- global 写入选项:写入全局的 ~/.gitconfig 文件而不是版本库的 .git/config,如果 ~/.gitconfig 文件不存在,则 ...