分治与汉诺塔问题

分治与汉诺塔

分治算法

分治算法介绍

  1. 分治法是一种很重要的算法。字面上的解释是“分而治之”,就是把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题……直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并。这个技巧是很多高效算法的基础,如排序算法(快速排序归并排序),傅立叶变换(快速傅立叶变换)……
  2. 分治算法可以求解的一些经典问题
  • 二分搜索
  • 大整数乘法
  • 棋盘覆盖
  • 合并排序
  • 快速排序
  • 线性时间选择
  • 最接近点对问题
  • 循环赛日程表
  • 汉诺塔

分治算法的基本步骤

1.分治法在每一层递归上都有三个步骤:

2.分解:将原问题分解为若干个规模较小,相互独立,与原问题形式相同的子问题

3.解决:若子问题规模较小而容易被解决则直接解,否则递归地解各个子问题

4.合并:将各个子问题的解合并为原问题的解。

分治(Divide-and-Conquer(P))算法设计模式如下


if |P|≤n0

then return(ADHOC(P))

//将P分解为较小的子问题 P1 ,P2 ,…,Pk

for i←1 to k

do yi ← Divide-and-Conquer(Pi)   递归解决Pi

T ← MERGE(y1,y2,…,yk)   合并子问题

return(T)

其中|P|表示问题P的规模;n0为一阈值,表示当问题P的规模不超过n0时,问题已容易直接解出,不必再继续分解。ADHOC(P)是该分治法中的基本子算法,用于直接解小规模的问题P。因此,当P的规模不超过n0时直接用算法ADHOC(P)求解。算法MERGE(y1,y2,…,yk)是该分治法中的合并子算法,用于将P的子问题P1 ,P2 ,…,Pk的相应的解y1,y2,…,yk合并为P的解。

分治算法最佳实践-汉诺塔

  • 汉诺塔的传说

汉诺塔:汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具。大梵

天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。

假如每秒钟一次,共需多长时间呢?移完这些金片需要5845.54亿年以上,太阳系的预期寿命据说也就是数百亿年。真的过了5845.54亿年,地球上的一切生命,连同梵塔、庙宇等,都早已经灰飞烟灭。

分治算法最佳实践-汉诺塔

汉诺塔游戏的演示和思路分析:

  1. 如果是有一个盘, A->C

如果我们有 n >= 2 情况,我们总是可以看做是两个盘 1.最下边的盘 2. 上面的盘

1. 先把 最上面的盘 A->B  移动过程会使用到 c

  1. hanoiTower(num - 1, a, c, b);

3. 把最下边的盘 A->C

  1. System.out.println("第" + num + "个盘从 " + a + "->" + c);

5. B塔的所有盘 从 B->C    移动过程会使用到 b

  1. hanoiTower(num - 1, b, a, c);

完整代码

package com.atguigu.dac;

public class Hanoitower {

        public static void main(String[] args) {
                hanoiTower(10, ‘A‘, ‘B‘, ‘C‘);
        }

        //汉诺塔的移动的方法
        //使用分治算法

        public static void hanoiTower(int num, char a, char b, char c) {
                //如果只有一个盘
                if(num == 1) {
                        System.out.println("第1个盘从 " + a + "->" + c);
                } else {
                        //如果我们有 n >= 2 情况,我们总是可以看做是两个盘 1.最下边的一个盘 2. 上面的所有盘
                        //1. 先把 最上面的所有盘 A->B, 移动过程会使用到 c
                        hanoiTower(num - 1, a, c, b);
                        //2. 把最下边的盘 A->C
                        System.out.println("第" + num + "个盘从 " + a + "->" + c);
                        //3. 把B塔的所有盘 从 B->C , 移动过程使用到 a塔
                        hanoiTower(num - 1, b, a, c);

                }
        }

}

原文地址:https://www.cnblogs.com/cnng/p/12333990.html

时间: 2024-10-10 17:51:30

分治与汉诺塔问题的相关文章

经典分治 - 汉诺塔游戏

分治策略: 将父问题划分为多个子问题(注:子问题与父问题一定要具有自相似性),然后找递归出口. 1.子问题规模变小.2.子问题与父问题本质等价. 汉诺塔游戏简述:三个柱A.B.C,将从大到小的盘按规则从A柱移到B柱. 具体的分治算法实现: 1 - N从A移动到B,C为辅助. 等价于: 1.1 - (N - 1)从A移动到C,B为辅助 2.把N从A移动到B 3.1 - (N - 1)从C移动到B,A为辅助 话说当时刚开始想这个问题的时候,我把2 - N当作一个子问题移动对象,将1盘移到辅助柱子上,

2017.11.26 计算机算法之分治与递归——汉诺塔

1.我的递归算法(纯粹的递归) #include <stdio.h>//当盘子数n等于15时,移动次数已经达到32767,运行时间已经达到15.540s long long count; void hanoi(int n,char a,char b,char c)//借助C将A上的盘子全部移动到B { if(n==0) return; hanoi(n-1,a,c,b); printf("%c --> %c\n",a,b); count++; hanoi(n-1,c,b

2.6 递归与分治策略(汉诺塔问题)

汉诺塔问题是一个经典问题. 题意理解:有A,B,C三个柱子,将A柱子上的N个盘子(从小到大排列)移到C柱子上,每次只允许移动一个盘子,并且保证每个柱子上的盘子的排列都是从小到大. 分析:由题意可知,如果要将A上的盘子移动到C,那么肯定需要借助C. 首先将A上的盘子从上到下依次编号为1-n. 运用整体思想: 1.假设1到n-1个盘子是一个整体 2.将1到n-1个盘子构成的整体移动到B 3.将第n个盘子移动到C 4.再将第2步移动到B的整体移动到C就可以了. 重复以上过程,显然这是一个递归的过程.下

分治法-汉诺塔问题

一 基本概念 分治法,顾名思义分而治之的意思,就是把一个复杂的问题分成两个或很多其它的同样或相似的子问题,再把子问题分成更小的子问题--直到最后子问题能够简单的直接求解,原问题的解即子问题的解的合并. 二基本思想及策略 分治法的设计思想是:将一个难以直接解决的大问题,切割成一些规模较小的同样问题,以便各个击破,分而治之. 分治策略是:对于一个规模为n的问题,若该问题能够easy地解决(比方说规模n较小)则直接解决,否则将其分解为k个规模较小的子问题,这些子问题互相独立且与原问题形式同样,递归地解

汉诺塔问题的递归实现

汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具.大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘.大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上.并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘. 1.汉诺塔(基本) 汉诺塔问题是典型的分治算法问题,首先我们来讨论最基本的汉诺塔问题.假设有n个圆盘,三根柱子,a,b,c,需要把n个盘子(从上往下从小到大摞着)从a柱移动到c柱,在小圆盘上不能放大圆盘,在三根柱

《算法四》(二分排序+汉诺塔问题)

二分查找:有序数组按照二分方式来查找数据 递归方法: //递归方式: int mid = l + (r-l)/2;//中间 if(l==r) return -1;//没有找到的情况 if(finddata==a[mid]) return mid; if(finddata>a[mid]) return half_find(a, mid+1, r, finddata); if(finddata<a[mid]) return half_find(a, l, mid, finddata); 非递归方法

C++ 汉诺塔问题

汉诺塔问题,是心理学实验研究常用的任务之一.当然我们是学计算机的,因此我们尝试用计算机去求解它. 例题 openjudge6261 汉诺塔问题 描述 有一种智力玩具,在一块铜板上有三根杆,最左边的杆上自上而下.由小到大顺序串着由n个圆盘构成的塔.目的是将最左边杆上的盘全部移到中间的杆上,条件是一次只能移动一个盘,且不允许大盘放在小盘的上面.这就是著名的汉诺塔问题. 假定圆盘从小到大编号为1,2,3,-- 输入 输入为一个整数后面跟三个单字符字符串. 整数为盘子的数目,后三个字符表示三个杆子的编号

hdu 1207 汉诺塔II (DP+递推)

汉诺塔II Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 4529    Accepted Submission(s): 2231 Problem Description 经典的汉诺塔问题经常作为一个递归的经典例题存在.可能有人并不知道汉诺塔问题的典故.汉诺塔来源于印度传说的一个故事,上帝创造世界时作了三根金刚石柱子,在一根柱子上从下往

从汉诺塔问题来看“递归”本质

汉诺塔问题 大二上数据结构课,老师在讲解"栈与递归的实现"时,引入了汉诺塔的问题,使用递归来解决n个盘在(x,y,z)轴上移动. 例如下面的动图(图片出自于汉诺塔算法详解之C++): 三个盘的情况: 四个盘的情况: 如果是5个.6个.7个....,该如何移动呢? 于是,老师给了一段经典的递归代码: void hanoi(int n,char x,char y,char z){ if(n == 1) move(x,1,z); else{ hanoi(n-1,x,z,y); move(x,