zoukankan      html  css  js  c++  java
  • 汉诺塔问题

      场景:三个柱子,左边从小到大排列,要把左边的全部移动到右边

      规则:移动必须要经过中间的柱子,任何柱子上不能违反从小到大排列的规则,打印移动过程和最优移动总步数。

      有两种解法:

      其中递归的解法如下:

        左边移动思路:想要移动最底下的到中间,就要移动上一个,依次递推,直到最上边的就可以移动到中间,然后要把右边的移动到左边,这样可以使当初移动到中间的那个移动到右边。右边的移动到左边也是左边移动思路的应用。

    public class SortHanoi {
    	Stack<Integer> stack1 = new Stack<Integer>();
    	Stack<Integer> stack2 = new Stack<Integer>();
    	Stack<Integer> stack3 = new Stack<Integer>();
    	int num = 0;
    	
    
    	public static void main(String[] args) {
    		SortHanoi sortHanoi = new SortHanoi();
    		sortHanoi.method1(2);
    		System.out.println("it will move "+sortHanoi.num+" steps");
    	}
    	
    	private void initHanoi(int tier) {
    		for (int i = tier; i > 0; i--) {
    			stack1.push(i);
    		}
    	}
    
    	private void method1(int tier) {
    
    		initHanoi(tier);
    		moveLeftToRight(tier);
    
    	}
    
    	private void moveLeftToRight(int level) {
    		if(level==1) {
    			move123();
    			return;
    		}else {
    			moveLeftToRight(level-1);
    			move12();
    			int rightLevel = stack3.size();
    			moveRightToLeft(rightLevel);
    			move23();
    			moveLeftToRight(rightLevel);
    			
    			
    		}
    	}
    	
    	private void moveRightToLeft(int level) {
    		if(level==1) {
    			move321();
    			return;
    		}else {
    			moveRightToLeft(level-1);
    			move32();
    			moveLeftToRight(level-1);
    			move21();
    			moveRightToLeft(level-1);
    			
    		}
    	}
    
    	private void move21() {
    		stack1.push(stack2.pop());
    		num++;
    		System.out.println("move "+stack1.peek()+" from mid to left");
    	}
    
    	private void move32() {
    		stack2.push(stack3.pop());
    		num++;
    		System.out.println("move "+stack2.peek()+" from right to mid");
    	}
    
    	private void move23() {
    		stack3.push(stack2.pop());
    		num++;
    		System.out.println("move "+stack3.peek()+" from mid to right");
    	}
    	
    	private void move12() {
    		stack2.push(stack1.pop());
    		num++;
    		System.out.println("move "+stack2.peek()+" from left to mid");
    	}
    
    	private void move321() {
    		move32();
    		move21();
    	}
    
    
    	private void move123() {
    		move12();
    		move23();
    	}
    
    }
    
    ////TODO 只有一个的时候
    //move123();
    ////TODO 只有两个的时候
    //move12();
    //
    //move23();
    ////TODO 只有三个的时候
    //move12();
    //	// 右边清空
    //	move32();
    //	move21();
    //
    //move23();
    //	//左边清空
    //	move12();
    //	move23();
    //	
    ////TODO 只有四个的时候
    //move12();
    //	// 右边清空
    //	move32();
    //	move21();
    //	move32();
    //	move12();
    //	move23();
    //	move21();
    //	move32();
    //	move21();
    //
    //move23();
    //	//左边清空
    //	move12();
    //	move23();
    //	move12();
    //	move32();
    //	move21();
    //	move23();
    //	move12();
    //	move23();
    

      

      另外一种是书中提供的:

        移动有四种可能,左右到中,或者中到左右。移动有两个规则,第一,不能反向,没有意义。第二,不能大压小,多以这样直接排除了两步。下一步就是比较剩下的两步哪一个没有违反这两个规则。这样从第一步开始,以后的每一步其实都是确定的了。

      第二种排除思路是很有借鉴性的

      在解决这个问题的时候,不能用常规的思路去推导移动的规律,这是这个算法问题的难点,也是这个算法问题的核心之处。

  • 相关阅读:
    mysql 按天创建分区存储过程
    Logstash下载安装使用并日志写入Mysql数据库
    开源BI分析工具Metabase配置与完全使用手册
    MySQL安装之yum安装
    IDEA创建SpringBoot
    JDK环境变量配置
    MySQL存储过程
    定时执行任务
    fastjson的使用——JSON字符串、JSON对象、Java对象的互转
    SQL反模式读书笔记思维导图
  • 原文地址:https://www.cnblogs.com/cambra/p/13705419.html
Copyright © 2011-2022 走看看