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. 测试linux python import module

    源码test.py #!/usr/bin/env python # -*- coding: UTF-8 -*- import os os.system("df -h") 运行结果( ...

  2. Qt5完美解决 界面显示中文乱码

    最近在学习Qt,可是一直头疼于中文乱码问题,上网搜了一下,很多都是Qt4中使用如下方法: QTextCodec *codec = QTextCodec::codecForName("gbk& ...

  3. Servlet过滤器----Filter

    JavaEE的Servlet规范描述了三种技术:Servlet,Filter,Listener (一)过滤器简介 Filter也称之为过滤器,它是Servlet技术中最实用的技术,WEB开发人员通过F ...

  4. Java的Class类及static块的执行时机

    要理解RTTI在Java中的工作原理,首先必须知道类型信息在运行时是如何表示的,这项工程由Class对象完成,它包含了与类有关的信息.Java使用Class对象来执行其RTTI,即使你执行的是类似转型 ...

  5. FPGA nios软核编写液晶屏LCD12864驱动程序源码以及注意事项,本人亲自踩坑,重要!!!

    LCD12864引脚如下: FPGA开发板得提供,3.3v电压,5v电压,普通io都是3.3v电压 DB:数据脚,得用双向io,因为程序里面需要读取液晶的应答(普通io3.3v可以) E:?输出引脚即 ...

  6. MySQL——MySQL初始化配置文件

    初始化配置文件(影响服务器和客户端程序) 1.MySQL初始化配置加载顺序: 命令行 ----> 初始化配置文件 ----> 预编译选项 2.MySQL初始化配置文件加载顺序: (1)/e ...

  7. Robot Framework(8)- Collections 测试库常用的关键字列表

    如果你还想从头学起Robot Framework,可以看看这个系列的文章哦! https://www.cnblogs.com/poloyy/category/1770899.html 前言 所有关键字 ...

  8. ubantu虚拟机搭建xl2tp服务

    在编译成功源码,安装完毕xl2tpd后,便可以配置xl2tpd服务.基本配置过程主要涉及两个配置文件:一个用来配置xl2tpd, 一个用来配置ppp协议.下面分别对这两个文件进行说明,最后添加xl2t ...

  9. Fastjson 1.2.22-24 反序列化漏洞分析(2)

    Fastjson 1.2.22-24 反序列化漏洞分析(2) 1.环境搭建 我们以ubuntu作为被攻击的服务器,本机电脑作为攻击者 本机地址:192.168.202.1 ubuntu地址:192.1 ...

  10. 详解Java中==和equals()的区别

    众所周知,在 Java 编程中,程序员通常会使用==或equals()来简单的比较地址,内容是否相等.而这两者之间的使用区别,对于初学 Java 的同学来说可能会比较迷糊.我将根据下面的几段示例程序, ...