P4285 [SHOI2008]汉诺塔
题目描述
汉诺塔由三根柱子(分别用A、B、C表示)和n个大小互不相同的空心盘子组成。一开始n个盘子都摞在柱子A上,大的在下面,小的在上面,形成了一个塔状的锥形体。 对汉诺塔的一次合法的操作是指:从一根柱子的最上层拿一个盘子放到另一根柱子的最上层,同时要保证被移动的盘子一定放在比它更大的盘子上面(如果移动到空柱子上就不需要满足这个要求)。我们可以用两个字母来描述一次操作:第一个字母代表起始柱子,第二个字母代表目标柱子。例如,AB就是把柱子A最上面的那个盘子移到柱子B。汉诺塔的游戏目标是将所有的盘子从柱子A移动到柱子B或柱子C上面。 有一种非常简洁而经典的策略可以帮助我们完成这个游戏。首先,在任何操作执行之前,我们以任意的次序为六种操作(AB、AC、BA、BC、CA和CB)赋予不同的优先级,然后,我们总是选择符合以下两个条件的操作来移动盘子,直到所有的盘子都从柱子A移动到另一根柱子: (1)这种操作是所有合法操作中优先级最高的; (2)这种操作所要移动的盘子不是上一次操作所移动的那个盘子。 可以证明,上述策略一定能完成汉诺塔游戏。现在你的任务就是假设给定了每种操作的优先级,计算按照上述策略操作汉诺塔移动所需要的步骤数。

输入输出格式
输入格式:
输入有两行。第一行为一个整数n(1≤n≤30),代表盘子的个数。第二行是一串大写的ABC字符,代表六种操作的优先级,靠前的操作具有较高的优先级。每种操作都由一个空格隔开。
输出格式:
只需输出一个数,这个数表示移动的次数。我们保证答案不会超过10的18次方。
输入输出样例
3
AB BC CA BA CB AC
7
2
AB BA CA BC CB AC
5
说明
对于20%的数据,n ≤ 10。 对于100%的数据,n ≤ 30。
Solution:
本题由于题面中说道按照上述方法一定能有答案。
那么我们由普通的$hanoi$三塔的递推式:$d[i]=2*d[i-1]+1$(现实意义是将$i-1$个移动到$B$柱,再将$A$柱的一个移动到$C$柱,最后把$B$柱的$i-1$个移动到$C$柱),具体证明直接数归,还是比较简单的。
然后扩展到本题,我们可以直接$dfs$处理出$n=1,2,3$的情况所对应的$d[1],d[2],d[3]$。
由数归不难得出:$d[i]=k*d[i-1]+b$(可以类比普通$hanoi$塔)。
则$k=\frac{d[3]-d[2]}{d[2]-d[1]},\;b=d[3]-d[2]*k$。
最后$O(n)$递推即可得到$d[n]$了。
代码:
#include<bits/stdc++.h>
#define For(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
#define il inline
#define ll long long
using namespace std;
const int N=;
int n;
ll d[N];
int stk[][],cnt[];
struct node{
int fr,to;
}a[N];
bool vis[];
char s[];
il void dfs(int p,int c,int lst){
if(cnt[]==c||cnt[]==c){d[c]=p;return;}
For(i,,){
int j=a[i].fr,k=a[i].to;
if(cnt[j]&&j!=lst){
if(stk[j][cnt[j]]<stk[k][cnt[k]]||!stk[k][cnt[k]]){
stk[k][++cnt[k]]=stk[j][cnt[j]];
cnt[j]--;
dfs(p+,c,k);
break;
}
}
}
}
int main(){
scanf("%d",&n);
For(i,,){
scanf("%s",s);
a[i].fr=s[]-'A',a[i].to=s[]-'A';
}
stk[][++cnt[]]=;
dfs(,,-);
cnt[]=cnt[]=cnt[]=;
For(i,,)stk[][++cnt[]]=-i;
dfs(,,-);
cnt[]=cnt[]=cnt[]=;
For(i,,)stk[][++cnt[]]=-i;
dfs(,,-);
if(n<=)cout<<d[n];
else {
ll k=(d[]-d[])/(d[]-d[]),q=d[]-k*d[];
For(i,,n)d[i]=1ll*k*(d[i-])+q;
cout<<d[n];
}
return ;
}
P4285 [SHOI2008]汉诺塔的更多相关文章
- bzoj1019 / P4285 [SHOI2008]汉诺塔
P4285 [SHOI2008]汉诺塔 递推 题目给出了优先级,那么走法是唯一的. 我们用$0,1,2$代表$A,B,C$三个柱子 设$g[i][x]$为第$x$根柱子上的$i$个盘子,经过演变后最终 ...
- BZOJ1019 汉诺塔/洛谷P4285 [SHOI2008]汉诺塔
汉诺塔(BZOJ) P4285 [SHOI2008]汉诺塔 居然是省选题,还是DP!(我的DP菜得要死,碰见就丢分) 冥思苦想了1h+ \(\to\) ?! 就是普通的hanoi NOI or HNO ...
- P4285 [SHOI2008]汉诺塔 题解 (乱搞)
题目链接 P4285 [SHOI2008]汉诺塔 解题思路 提供一种打表新思路 先来证明一个其他题解都没有证明的结论:\(ans[i]\)是可由\(ans[i-1]\)线性递推的. (\(ans[i] ...
- 1019: [SHOI2008]汉诺塔
1019: [SHOI2008]汉诺塔 Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 1495 Solved: 916[Submit][Status] ...
- bzoj1019 [SHOI2008]汉诺塔
1019: [SHOI2008]汉诺塔 Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 1030 Solved: 638[Submit][Status] ...
- BZOJ 1019: [SHOI2008]汉诺塔( dp )
dp(x, y)表示第x根柱子上y个盘子移开后到哪根柱子以及花费步数..然后根据汉诺塔原理去转移... ------------------------------------------------ ...
- 【BZOJ1019】[SHOI2008]汉诺塔(数论,搜索)
[BZOJ1019][SHOI2008]汉诺塔(数论,搜索) 题面 BZOJ 洛谷 题解 首先汉诺塔问题的递推式我们大力猜想一下一定会是形如\(f_i=kf_{i-1}+b\)的形式. 这个鬼玩意不好 ...
- bzoj千题计划109:bzoj1019: [SHOI2008]汉诺塔
http://www.lydsy.com/JudgeOnline/problem.php?id=1019 题目中问步骤数,没说最少 可以大胆猜测移动方案唯一 (真的是唯一但不会证) 设f[i][j] ...
- 【BZOJ 1019】 1019: [SHOI2008]汉诺塔 (DP?)
1019: [SHOI2008]汉诺塔 Description 汉诺塔由三根柱子(分别用A B C表示)和n个大小互不相同的空心盘子组成.一开始n个盘子都摞在柱子A上,大的在下面,小的在上面,形成了一 ...
随机推荐
- poj_1730_Perfect Pth Powers
We say that x is a perfect square if, for some integer b, x = b 2. Similarly, x is a perfect cube if ...
- keepalived实现nginx的高可用
1.使用yum安装keepalived yum install keepalived -y 2.修改配置文件keepalived.conf 主服务器配置文件 global_defs { router_ ...
- 天气预报api-汇总
和风天气 https://www.heweather.com/
- delphi的消息对话框
delphi的消息对话框,类似VFP中的WAIT和MESSAGEBOXdelphi的消息对话框,类似VFP中的WAIT和MESSAGEBOX1.最简单的是:showmessage() 它只有一个OK按 ...
- javascript 运行机制 事件循环 浏览器缓存 (慕课网 前段跳槽面试必备 4-1,4-2,4-3)
4-1 渲染机制:-1-,什么是DOCTYPE及其作用?DTD(document type definition,文档类型定义)是一系列的语法规则,用来定义XML或(X)HTML的文件类型,浏览器会使 ...
- ADSL_自动拨号源码(Delphi),已经测试通过
下载地址: http://files.cnblogs.com/lwm8246/ADSL_%E8%87%AA%E5%8A%A8%E6%8B%A8%E5%8F%B7.rar
- bedtools
- C语言指针篇(一)指针与指针变量
指针 1. 什么是指针? 2. 指针可不可怕? 3. 指针好不好玩? 4. 怎么学好指针? C语言是跟内存打交道的语言,指针就是内存地址.指针无处不在,指针并不可怕,相反,等你学到一定程 ...
- Python 文本挖掘:使用情感词典进行情感分析(算法及程序设计)
出处:http://www.ithao123.cn/content-242299.html 情感分析就是分析一句话说得是很主观还是客观描述,分析这句话表达的是积极的情绪还是消极的情绪. 原理 比如 ...
- Android面试收集录13 Android虚拟机及编译过程
一.什么是Dalvik虚拟机 Dalvik是Google公司自己设计用于Android平台的Java虚拟机,它是Android平台的重要组成部分,支持dex格式(Dalvik Executable)的 ...