uoj167 元旦老人与汉诺塔(记忆化搜索)
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 元旦老人与汉诺塔(记忆化搜索)的更多相关文章
- [UOJ #167]【UR #11】元旦老人与汉诺塔
题目大意:给你一个有$n$个盘子的汉诺塔状态$S$,问有多少种不同的操作方法,使得可以在$m$步以内到达状态$T$.$n,m\leqslant100$ 题解:首先可以知道的是,一个状态最多可以转移到其 ...
- UR11 A.元旦老人与汉诺塔
题目:http://uoj.ac/contest/23/problem/167 如果我们拿个map来存状态的话.设当前状态是v,下一个状态是s.有f[i+1][s]+=f[i][v]. 初始f[0][ ...
- 奇妙的算法【4】-汉诺塔&哈夫曼编码
1,汉诺塔问题[还是看了源码才记起来的,记忆逐渐清晰] 汉诺塔:汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具.大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着6 ...
- 算法笔记_013:汉诺塔问题(Java递归法和非递归法)
目录 1 问题描述 2 解决方案 2.1 递归法 2.2 非递归法 1 问题描述 Simulate the movement of the Towers of Hanoi Puzzle; Bonus ...
- C#递归解决汉诺塔问题(Hanoi)
using System;using System.Collections.Generic;using System.Linq;using System.Text; namespace MyExamp ...
- 数据结构0103汉诺塔&八皇后
主要是从汉诺塔及八皇后问题体会递归算法. 汉诺塔: #include <stdio.h> void move(int n, char x,char y, char z){ if(1==n) ...
- Conquer and Divide经典例子之汉诺塔问题
递归是许多经典算法的backbone, 是一种常用的高效的编程策略.简单的几行代码就能把一团遭的问题迎刃而解.这篇博客主要通过解决汉诺塔问题来理解递归的精髓. 汉诺塔问题简介: 在印度,有这么一个古老 ...
- 几年前做家教写的C教程(之四专讲了指针与汉诺塔问题)
C语言学习宝典(4) 指针:可以有效的表示复杂的数据结构,能动态的分配动态空间,方便的使用字符串,有效的使用数组,能直接处理内存单元 不掌握指针就没有掌握C语言的精华 地址:系统为每一个变量分配一个内 ...
- python实现汉诺塔
经典递归算法汉诺塔分析: 当A柱子只有1个盘子,直接A --> C 当A柱子上有3个盘子,A上第一个盘子 --> B, A上最后一个盘子 --> C, B上所有盘子(1个) --&g ...
随机推荐
- 测试linux python import module
源码test.py #!/usr/bin/env python # -*- coding: UTF-8 -*- import os os.system("df -h") 运行结果( ...
- Qt5完美解决 界面显示中文乱码
最近在学习Qt,可是一直头疼于中文乱码问题,上网搜了一下,很多都是Qt4中使用如下方法: QTextCodec *codec = QTextCodec::codecForName("gbk& ...
- Servlet过滤器----Filter
JavaEE的Servlet规范描述了三种技术:Servlet,Filter,Listener (一)过滤器简介 Filter也称之为过滤器,它是Servlet技术中最实用的技术,WEB开发人员通过F ...
- Java的Class类及static块的执行时机
要理解RTTI在Java中的工作原理,首先必须知道类型信息在运行时是如何表示的,这项工程由Class对象完成,它包含了与类有关的信息.Java使用Class对象来执行其RTTI,即使你执行的是类似转型 ...
- FPGA nios软核编写液晶屏LCD12864驱动程序源码以及注意事项,本人亲自踩坑,重要!!!
LCD12864引脚如下: FPGA开发板得提供,3.3v电压,5v电压,普通io都是3.3v电压 DB:数据脚,得用双向io,因为程序里面需要读取液晶的应答(普通io3.3v可以) E:?输出引脚即 ...
- MySQL——MySQL初始化配置文件
初始化配置文件(影响服务器和客户端程序) 1.MySQL初始化配置加载顺序: 命令行 ----> 初始化配置文件 ----> 预编译选项 2.MySQL初始化配置文件加载顺序: (1)/e ...
- Robot Framework(8)- Collections 测试库常用的关键字列表
如果你还想从头学起Robot Framework,可以看看这个系列的文章哦! https://www.cnblogs.com/poloyy/category/1770899.html 前言 所有关键字 ...
- ubantu虚拟机搭建xl2tp服务
在编译成功源码,安装完毕xl2tpd后,便可以配置xl2tpd服务.基本配置过程主要涉及两个配置文件:一个用来配置xl2tpd, 一个用来配置ppp协议.下面分别对这两个文件进行说明,最后添加xl2t ...
- Fastjson 1.2.22-24 反序列化漏洞分析(2)
Fastjson 1.2.22-24 反序列化漏洞分析(2) 1.环境搭建 我们以ubuntu作为被攻击的服务器,本机电脑作为攻击者 本机地址:192.168.202.1 ubuntu地址:192.1 ...
- 详解Java中==和equals()的区别
众所周知,在 Java 编程中,程序员通常会使用==或equals()来简单的比较地址,内容是否相等.而这两者之间的使用区别,对于初学 Java 的同学来说可能会比较迷糊.我将根据下面的几段示例程序, ...