poj1958-汉诺四塔问题(三种方法)

链接:http://poj.org/problem?id=1958
大意:汉诺塔升级版,四根柱子,n个盘子,求最少移动次数;

两种方法 递推or递归(当然还有思路3——打表)

思路1:递推(或者DP?)

把四塔转换为三塔进行思考
假设当前要移动n个盘子,那么就不如分为以下几步
先将上面的i个盘子移到第2或3个塔上;(四塔移动)
再把剩下的(n-i)个盘子移到最后一个塔上(三塔移动);
最后把在那i个盘子移到最后一个塔上(注意:是四塔移动,i个盘子一定比后来的(n-i)个盘子小)

得到方程:f[n]=min{2f[i]+d[n-i]};
注:f[i]为四塔移动的最小步数,d[i]为三塔移动的最小步数(此处不再多说,都知道是2^i-1了,由于题面要求12,打表就行,由于两次四塔移动,一次三塔移动,所以F[N]
2)

核心代码:

for(int i=1;i<=n;i++)
    {
        f[n]=min(f[n],2*f[i]+d[n-i]);
    }

AC代码

#include<cstdio>
#include<iostream>
#include<cctype>
#include<algorithm>
using namespace std;

inline int read()
{
    int ans=0,f=1;
    char chr=getchar();
    while(!isdigit(chr)) {if(chr='-') f=-1; chr=getchar();}
    while(isdigit(chr)) {ans=ans*10+chr-'0'; chr=getchar();}
    return ans*f;
}//没有读入,依然要坚持加上/笑哭
int f[20]={0};
int d[]={0,1,3,7,15,31,63,127,255,511,1023,2047,4095};
int main()
{
    int n=1;
    f[1]=1;
    f[2]=3;
    for(n;n<=12;n++)
    {
        if(f[n])
        {
            printf("%d\n",f[n]);
            continue;
        }
        f[n]=0x3f3f3f3f;
        for(int i=1;i<=n;i++)
        {
            f[n]=min(f[n],2*f[i]+d[n-i]);
        }
        printf("%d\n",f[n]);
    }
    return 0;
}

思路2:递归

总体思路一模一样,实现有区别而已;

#include<cstdio>
#include<iostream>
#include<cctype>
#include<cstring>
#include<algorithm>
using namespace std;

inline int read()
{
    int ans=0,f=1;
    char chr=getchar();
    while(!isdigit(chr)) {if(chr='-') f=-1; chr=getchar();}
    while(isdigit(chr)) {ans=ans*10+chr-'0'; chr=getchar();}
    return ans*f;
}
int f[20];
int d[]={0,1,3,7,15,31,63,127,255,511,1023,2047,4095};
int hanoi(int x)
{
    if(f[x])
        return f[x];//记忆化(这个算吗/晕)
    if(x==0)
        return 0;
    if(x==1)
        return f[1]=1;
    f[x]=0x3f3f3f3f;
    for(int i=1;i<x;i++)
        f[x]=min(f[x],2*hanoi(i)+d[x-i]);//方程;
    return f[x];
}

int main()
{
    memset(f,0,sizeof(f));
    hanoi(12);
    for(int i=1;i<=12;i++)
        printf("%d\n",f[i]);
    return 0;
}

思路3:打表(hmmmm)

可以说是最快的思路了

#include<cstdio>
#include<iostream>
#include<cctype>
#include<algorithm>
using namespace std;

inline int read()
{
    int ans=0,f=1;
    char chr=getchar();
    while(!isdigit(chr)) {if(chr='-') f=-1; chr=getchar();}
    while(isdigit(chr)) {ans=ans*10+chr-'0'; chr=getchar();}
    return ans*f;
}
int f[]={0,1,3,5,9,13,17,25,33,41,49,65,81};
int main()
{
    for(int i=1;i<=12;i++)
        printf("%d\n",f[i]);
    return 0;
}

原文地址:https://www.cnblogs.com/zhenglw/p/9507923.html

时间: 2024-11-05 18:27:09

poj1958-汉诺四塔问题(三种方法)的相关文章

ubuntu/linux mint 创建proc文件的三种方法(四)

在做内核驱动开发的时候,可以使用/proc下的文件,获取相应的信息,以便调试. 大多数/proc下的文件是只读的,但为了示例的完整性,都提供了写方法. 方法一:使用create_proc_entry创建proc文件(简单,但写操作有缓冲区溢出的危险): 方法二:使用proc_create和seq_file创建proc文件(较方法三简洁): 方法三:使用proc_create_data和seq_file创建proc文件(较麻烦,但比较完整): 示例四:在proc文件中使用内核链表的一个示例(用的方

Oracle数据库备份与恢复的三种方法

转自blueskys567原文Oracle数据库备份与恢复的三种方法, 2006-10. 有删改 Oracle数据库有三种标准的备份方法,它们分别是导出/导入(EXP/IMP).热备份和冷备份. 导出备件是一种逻辑备份,冷备份和热备份是物理备份. 一. 导出/导入(Export/Import) 利用Export可将数据从数据库中提取出来,利用Import则可将提取出来的数据送回到Oracle数据库中去. 1. 简单导出数据(Export)和导入数据(Import) Oracle支持三种方式类型的

ubuntu/linux mint 创建proc文件的三种方法(二)

在做内核驱动开发的时候,可以使用/proc下的文件,获取相应的信息,以便调试. 大多数/proc下的文件是只读的,但为了示例的完整性,都提供了写方法. 方法一:使用create_proc_entry创建proc文件(简单,但写操作有缓冲区溢出的危险): 方法二:使用proc_create和seq_file创建proc文件(较方法三简洁): 方法三:使用proc_create_data和seq_file创建proc文件(较麻烦,但比较完整): 示例四:在proc文件中使用内核链表的一个示例(用的方

查看登陆系统用户的信息的三种方法详解

查看登陆系统用户的信息的三种方法详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.who这个命令显示可以谁在登陆,但是这个有很多的花式玩法,这个命令超简单 语法:who [OPTION]... [ FILE | ARG1 ARG2 ] 1.参数:-u,显示闲置时间,若该用户在前一分钟之内有进行任何动作,将标示成"."号,如果该用户已超过24小时没有任何动作,则标示出"old"字符串. 例如: 2.参数:-m,此参数的效果和指定"a

ubuntu/linux mint 创建proc文件的三种方法(一)

在做内核驱动开发的时候,可以使用/proc下的文件,获取相应的信息,以便调试. 大多数/proc下的文件是只读的,但为了示例的完整性,都提供了写方法. 方法一:使用create_proc_entry创建proc文件(简单,但写操作有缓冲区溢出的危险): 方法二:使用proc_create和seq_file创建proc文件(较方法三简洁): 方法三:使用proc_create_data和seq_file创建proc文件(较麻烦,但比较完整): 示例四:在proc文件中使用内核链表的一个示例(用的方

用旭日图展示数据的三种方法

什么是旭日图? 旭日图(Sunburst Chart)是一种现代饼图,它超越传统的饼图和环图,能表达清晰的层级和归属关系,以父子层次结构来显示数据构成情况.旭日图中,离远点越近表示级别越高,相邻两层中,是内层包含外层的关系. 在实际项目中使用旭日图,可以更细分溯源分析数据,真正了解数据的具体构成.而且,旭日图不仅数据直观,而且图表用起来特别炫酷,分分钟拉高数据汇报的颜值!很多数据场景都适合用旭日图,比如,在销售汇总报告中,方便看到每个店铺的销售业绩分布(如下图): 做旭日图的三种方法 1. 用E

实例365(8)---------三种方法将字符串格式化为日期

一:DateTime.ParseExact方式,截图 二:代码 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace ConvertToString { public

ubuntu/linux mint 创建proc文件的三种方法(三)

在做内核驱动开发的时候,可以使用/proc下的文件,获取相应的信息,以便调试. 大多数/proc下的文件是只读的,但为了示例的完整性,都提供了写方法. 方法一:使用create_proc_entry创建proc文件(简单,但写操作有缓冲区溢出的危险): 方法二:使用proc_create和seq_file创建proc文件(较方法三简洁): 方法三:使用proc_create_data和seq_file创建proc文件(较麻烦,但比较完整): 示例四:在proc文件中使用内核链表的一个示例(用的方

MySQL数据库的备份与恢复的三种方法

MySQL数据库的备份与恢复的三种方法 1.利用mysqldump实现从逻辑角度完全备份mysql,配合二进制日志备份实现增量备份 2.利用lvs快照从物理角度实现几乎热备的完全备份,配合二进制日志备份实现增量备份 3.利用percona公司的xrabackup实现完全热备份与增量热备份 实验环境:RHEL5.8 ,SElinux关闭,MySQL是tar包初始化安装版本5.5.28 一.测试环境准备 1.1 mysql的安装就不说了,见http://laoguang.blog.51cto.com

Java/JSP获得客户端网卡MAC地址的三种方法解析

java/jsp获得客户端(IE)网卡MAC地址的方法大概有三种. 1.通过命令方式,在客户端执行Ipconfig 等等.(java/jsp) 2.通过ActiveX的方法.(jsp) 3.通过向137的端口发送查询指令的方法.(java/jsp) 简介: 第一种方法,在真正用到时候不知道为什么获得mac地址的指令阻塞了,不往下继续执行.而且速度是这三种方法中最慢的一种. 代码如下: String sip=""; String smac=""; sip = requ