题目链接

题目大意:把汉诺双塔按指定顺序排好的最少步数

我写这题写了很久...终于发现不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的更多相关文章

  1. POJ1958:Strange Towers of Hanoi

    我对状态空间的理解:https://www.cnblogs.com/AKMer/p/9622590.html 题目传送门:http://poj.org/problem?id=1958 题目要我们求四柱 ...

  2. The Towers of Hanoi Revisited---(多柱汉诺塔)

    Description You all must know the puzzle named "The Towers of Hanoi". The puzzle has three ...

  3. [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 ...

  4. POJ 1958 Strange Towers of Hanoi

    Strange Towers of Hanoi Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 3784 Accepted: 23 ...

  5. ural 2029 Towers of Hanoi Strike Back (数学找规律)

    ural 2029 Towers of Hanoi Strike Back 链接:http://acm.timus.ru/problem.aspx?space=1&num=2029 题意:汉诺 ...

  6. POJ1958 Strange Towers of Hanoi [递推]

    题目传送门 Strange Towers of Hanoi Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 3117   Ac ...

  7. poj 1920 Towers of Hanoi

    Towers of Hanoi Time Limit: 3000MS   Memory Limit: 16000K Total Submissions: 2213   Accepted: 986 Ca ...

  8. 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 ...

  9. 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 ...

随机推荐

  1. winform使用相关

    1.回车键触发按钮点击事件——回车登录 设置窗体的AccessButton属性 2.密码框样式设置 设置PasswordChar为想要的密码显示的样式,如*  3.设置窗口居中 设置StartPosi ...

  2. opencv2\core\cuda.hpp(106): error C2059: 语法错误:“常量”

    在 cuda.hpp 中, virtual void free(GpuMat* mat) = 0;   -> virtual void _free(GpuMat* mat) = 0;

  3. 【学亮IT手记】PL/SQL游标编程

    游标提供了一种从表中检索数据并进行操作的灵活手段,主要用在服务器上,处理由客户端发送给服务器端的sql语句,或者是批处理.存储过程.触发器中的数据处理请求. 显式游标 是由用户声明和操作的一种游标,通 ...

  4. JSON Support in PostgreSQL and Entity Framework

    JSON 和JSONB的区别(What's difference between JSON and JSONB data type in PosgresSQL?) When should be use ...

  5. MyBatis映射文件6

    之前说了由Employee找Department,这一节讲一讲由Department找Employee,显然前者是多对一的关系,而后者是一对多的关系. Department的JavaBean: pri ...

  6. 手机端图像编辑上传-cropper

    编辑头像,实现相册,照像功能,并能缩放裁剪功能,可自定义UI,引用'cropper.js', 'exif.js' /*初始化裁剪插件*/ var screenWidth = $(window).wid ...

  7. java学习之—递归

    /** * 递归 * Create by Administrator * 2018/6/20 0020 * 上午 9:41 **/ public class TriangleApp { static ...

  8. LODOP暂存、应用、复原 按钮的区别

    LODOP中打印设计(PRINT_DESIGN)有暂存和复原按钮,打印维护(PRINT_SETUP)有应用和复原按钮. 打印设计暂存和打印维护的应用功能不同,两者的区别:1.打印设计的暂存.复原(类似 ...

  9. solr单机版搭建

    需要把solr服务器安装到linux环境: 第一步:安装linux.jdk.tomcat. [root@bogon ~]# ll total 8044 -rw-r--r--. 1 root root ...

  10. Java线程的创建方式三:Callable(四)

    一.Java实现多线程的三种方式 方式一:继承Thread类: public class Test extends Thread { public static void main(String[] ...