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 ...
随机推荐
- 有关spring注解总结
前言 目前企业开发多采用纯注解的方式开发,注解开发的好处:简洁,可读性强 最近学习了spring全家桶,总结了有关spring的常用注解,写的不对的地方,欢迎指正 Spring模块注解 @Config ...
- Linux压缩解压 tar.gz格式的文件.查看tomcat是否运行
tar命令详解 -c: 建立压缩档案 -x:解压 -t:查看内容 -r:向压缩归档文件末尾追加文件 -u:更新原压缩包中的文件 这五个是独立的命令,压缩解压都要用到其中一个,可以和别的命令连用但只能用 ...
- Spring Boot 入门系列(二十四)多环境配置,3分钟搞定!
之前讲过Spring Boot 的系统配置和自定义配置,实现了按照实际项目的要求配置系统的相关熟悉.但是,在实际项目开发过程中,需要面对不同的环境,例如:开发环境,测试环境,生产环境.各个环境的数据库 ...
- noip模拟30
\(\color{white}{\mathbb{缀以无尽之群星点点,饰以常青之巨木郁郁,可细斟木纹叶脉,独无可极苍穹之览,名之以:密林}}\) 看完题后感觉整套题都没什么思路,而且基本上整场考试确实是 ...
- [考试总结]noip模拟39
不写那么多没用的了 开题就发现 \(T4\) 原题, \(T1\) 大水题. 然后发现 \(T4\) 忘了.... 不扯了 打地鼠 大水题,我代码都不想放... 算了,还是放一下吧.. #includ ...
- Python - //和/的区别
/ 表示浮点数除法,返回浮点结果; // 表示整数除法,返回不大于结果的一个最大的整数 print("6 // 4 = " + str(6 // 4)) print("6 ...
- Python - 文件模式a+读取不了文件
代码 f = open('test/gbk.txt', 'a+', encoding='utf-8') print(f.readline()) 最终的执行结果是输出空,为什么呢? a+模式打开文件指针 ...
- 第七章:网络优化与正则化(Part2)
文章相关 1 第七章:网络优化与正则化(Part1) 2 第七章:网络优化与正则化(Part2) 7.3 参数初始化 神经网络的参数学习是一个非凸优化问题.当使用梯度下降法来进行优化网络参数时,参数初 ...
- 【C++基础教程】第五课
上次的作业答案,非常简单. 第一题: 我们需要知道,字符(char类型)在计算机中存储的时候,是把这个字符对应的代码(专业术语叫做编码)进行存储.例如,换行符'\n'的代码就是10,'0'对应的代码就 ...
- PHP中环境变量的操作
在 PHP 中,我们可以通过 phpinfo() 查看到当前系统中的环境变量信息(Environment).在代码中,我们也可以通过两个函数,查看和修改相应的环境变量信息. getenv() 获取环境 ...