Gym-100451B:Double Towers of Hanoi
题目大意:把汉诺双塔按指定顺序排好的最少步数
我写这题写了很久...终于发现不dp不行
把一个双重塔从一根桩柱移动到另一根桩柱需要移动多少次?
最佳策略是移动一个双重 (n-1) 塔,接着移动两个最大的圆盘,然后再次移动双重 (n-1) 塔,从而 $A_n = 2 * A_{n-1} + 2,A_n = 2^{n+1} - 2 $。
这会交换两个最大的圆盘,其余的 \(2n-2\) 个圆盘次序不变。
如果在最后的排列中要把所有同样尺寸的圆盘恢复成原来的从上到下的次序,需要移动多少次?
有两个想法:(假设初始盘子都在A柱上)
一:先把双重(n-1)塔按顺序在C柱上搞好,再2步把最大的两个盘丢到B柱上,\(A_{n-1}\)步把双重(n-1)塔丢A柱子上,再2步把最大的两个盘丢到C柱上,最后\(A_{n-1}\)步把双重(n-1)塔丢C柱子上
发现这样顺序刚好是对的\(B_n=B_{n-1}+2^{n+1}\)
二:先把双重(n-1)塔按顺序在C柱上搞好,再移动靠上的一个大圆盘J到B柱,把(n-1)塔再移上B柱上的大圆盘,移动另一个大圆盘H,把(n-1)塔移到一根空柱上,把H放在J上,再把(n-1)塔移到两个大圆盘上,发现顺序刚好也是对的
\(B_n = A_{n-1} + 1 + A_{n-1} + 1 + A_{n-1} + 1 + A_{n-1} = 4A_{n-1} + 3 = 4(2^{n} - 2) + 3 = 2^{n+2} - 5\)
然后你发现这两个式子是等价的。。。
我的想法:除了最底下的两个盘子,如果两个盘子的顺序是倒过来的,那么在移动的时候就先正着与比它小的盘子放好一堆,在移动更大的两个盘子的时候用\(A_n\)的做法,顺序不就又倒过来了吗?
事实证明这是错的,无法保证最优性
所以dp吧
g[i]表示把前\(2(i-1)\)块按顺序排好,最后两块也按要求顺序排好的最小步数
f[i]表示把前\(2(i-1)\)块按顺序排好,最后两块与要求顺序相反最小步数
\(f[i]=g[i-1]+4+2^{i+1}-4=g[i-1]+2^{i+1}\)
表示先把i-1层按顺序移出去,再移动第i层,i-1层移到另一个柱上,再移动第i层,i-1层移到第i层上,这样顺序刚好是对的(类似\(B_i\)的移法)
\(g[i]=f[i-1]+2+ 2^i-2=f[i-1]+ 2^i\)
表示先把i-1层移出去,再把i层的两个盘移出,再把i-1层移上去
结合代码理解
#include<bits/stdc++.h>
#define rep(i,j,k) for(int i=j;i<=k;++i)
using namespace std;
typedef long long ll;
typedef double db;
char cch;
inline int rd(){
int x=0,fl=1;
cch=getchar();
while(cch>'9'||cch<'0'){
if(cch=='-') fl=-1;
cch=getchar();
}
while(cch>='0'&&cch<='9') x=(x<<3)+(x<<1)+cch-'0',cch=getchar();
return x*fl;
}
inline void add(int a[],int b[]){
int x=0,len=max(a[0],b[0]);
rep(i,1,len){
a[i]+=b[i]+x,x=a[i]/10000,a[i]%=10000;
}
if(x) a[++len]=x;
a[0]=len;
}
int p[2009][2009],f[2009],g[2009],a[4009];//注意是4009!
int main(){
int n=rd();
p[0][0]=1,p[0][1]=1;
rep(i,1,n+1) add(p[i],p[i-1]),add(p[i],p[i-1]);
rep(i,1,n) a[2*(n-i+1)]=rd(),a[2*(n-i+1)-1]=rd();
if(a[1]<a[2]) g[0]=1,g[1]=3,f[0]=1,f[1]=2;
else g[0]=1,g[1]=2,f[0]=1,f[1]=3;
int *ff=f,*gg=g;//这样可以只swap指针,swap数组是o(n)的
rep(i,2,n){
if(a[i*2]<a[i*2-1]) swap(ff,gg),add(ff,p[i+1]),add(gg,p[i]);//g是2 1顺序,f是1 2顺序,f[i]=g[i-1]+2^{i+1},g[i]=f[i-1]+2^i,所以swap
else add(ff,p[i]),add(gg,p[i+1]);//g是1 2,f是2 1, 此时g相当于上面的f,f相当于上面的g,所以转移方程互换
}
printf("%d",gg[gg[0]]);
for(int i=gg[0]-1;i;--i) printf("%04d",gg[i]);
}
/*
4
8 7 5 6 3 4 1 2
*/
Gym-100451B:Double Towers of Hanoi的更多相关文章
- POJ1958:Strange Towers of Hanoi
我对状态空间的理解:https://www.cnblogs.com/AKMer/p/9622590.html 题目传送门:http://poj.org/problem?id=1958 题目要我们求四柱 ...
- The Towers of Hanoi Revisited---(多柱汉诺塔)
Description You all must know the puzzle named "The Towers of Hanoi". The puzzle has three ...
- [CareerCup] 3.4 Towers of Hanoi 汉诺塔
3.4 In the classic problem of the Towers of Hanoi, you have 3 towers and N disks of different sizes ...
- POJ 1958 Strange Towers of Hanoi
Strange Towers of Hanoi Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 3784 Accepted: 23 ...
- ural 2029 Towers of Hanoi Strike Back (数学找规律)
ural 2029 Towers of Hanoi Strike Back 链接:http://acm.timus.ru/problem.aspx?space=1&num=2029 题意:汉诺 ...
- POJ1958 Strange Towers of Hanoi [递推]
题目传送门 Strange Towers of Hanoi Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 3117 Ac ...
- poj 1920 Towers of Hanoi
Towers of Hanoi Time Limit: 3000MS Memory Limit: 16000K Total Submissions: 2213 Accepted: 986 Ca ...
- zoj 2338 The Towers of Hanoi Revisited
The Towers of Hanoi Revisited Time Limit: 5 Seconds Memory Limit: 32768 KB Special Judge You all mus ...
- POJ 1958 Strange Towers of Hanoi 解题报告
Strange Towers of Hanoi 大体意思是要求\(n\)盘4的的hanoi tower问题. 总所周知,\(n\)盘3塔有递推公式\(d[i]=dp[i-1]*2+1\) 令\(f[i ...
随机推荐
- php获取URL扩展名
一切拿代码来说话: 举例:'http://www.sina.com.cn/abc/de/fg.php?id=1': $url = 'http://www.sina.com.cn/abc/de/fg.p ...
- Sqlserver tablediff的简单使用
1. 先列举一下自己简单的比较语句 tablediff -sourceserver 10.24.160.73 -sourcedatabase cwbasemi70 -sourceschema lcmi ...
- Spring中使用Ehcache的方法和注意事项
如何调用方法数据增加缓存 @Cacheable(value="MY_CACHE", key="'cache_business_' + #business_id" ...
- nodejs zip 安装配置
1.下载 下载地址:https://nodejs.org/zh-cn/download/ 选择相应的版本下载 2.解压缩 将文件解压到要安装的位置,并新建两个目录 node-global :npm全局 ...
- CSS3 flexbox 布局 ---- flex 容器属性介绍
flexbox布局是CSS3中新增的属性,它可以很轻松地帮我们解决掉一些常见的布局问题,比如导航栏. 我们用普通的方法写导航栏,通常会在ul, li 结构写好后,让li 元素左浮动,然后再给ul 清浮 ...
- 实验吧 WEB 猫抓老鼠
人生的第一道CTF题目哇,鸡冻 其实只是学了一下HTTP抓包得到的都是什么,就开始上手胡搞了 题目名字叫猫抓老鼠,还疯狂暗示catch!catch!catch!catch!,就想到要用抓包其实我是因为 ...
- python 模块之-shelve
shelve模块比pickle模块简单,只有一个open函数,返回类似字典的对象,可读可写;key必须为字符串,而值可以是python所支持的数据类型 import shelve f = shelve ...
- BZOJ4317Atm的树&BZOJ2051A Problem For Fun&BZOJ2117[2010国家集训队]Crash的旅游计划——二分答案+动态点分治(点分树套线段树/点分树+vector)
题目描述 Atm有一段时间在虐qtree的题目,于是,他满脑子都是tree,tree,tree…… 于是,一天晚上他梦到自己被关在了一个有根树中,每条路径都有边权,一个神秘的声音告诉他,每个点到其他的 ...
- L - Vases and Flowers HDU - 4614 线段树+二分
题意 给出一排空花瓶 有两种操作 1是 从A花瓶开始放F朵花 如果当前瓶有花就跳过前往下一个 直到花用完或者 瓶子到了最后一个为止 输出 成功放花的第一个和最后一个 如果没有输出 can not. ...
- ☆ [HDU4825] Xor Sum「最大异或和(Trie树)」
传送门:>Here< 题意:给出一个集合,包含N个数,每次询问给出一个数x,问x与集合中的一个数y异或得到最大值时,y是多少? 解题思路 由于N,M非常大,暴力显然不行.抓住重点是异或,所 ...