`
mabusyao
  • 浏览: 252660 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

汉诺塔的变种

阅读更多
1. 有三根柱子,在一根柱子上从下往上按大小顺序摞着n片圆盘。要求把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。

package hanoi;

/**
 * formulas:
 * T0 = 0
 * Tn = Tn-1 + 1
 * 
 * closed form:
 * Tn = 2(n) -1
 * 
 * @author yaoh
 *
 */
public class SimpleHanoi {

    public static int count = 0;

    public static void hanoi(String a, String b, String c, int n) {
        if(n <= 0)  System.out.println("No move needed.");
        
        if(n == 1) {
            System.out.println("Step "+ ++count+": move "+n+" from "+a+" to "+c);
        } else {
            hanoi(a, c, b, n - 1);
            
            System.out.println("Step "+ ++count+ ": move "+n+" from "+a+" to "+c);
            
            hanoi(b, a, c, n - 1);
        }
    }
    
    public static void main(String[] args) {
        hanoi("a", "b", "c", 5);
        
        System.out.println("Overall steps: " + count);
    }
}



2. 有四根柱子,在一根柱子上从下往上按大小顺序摞着n片圆盘。要求把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在四根柱子之间一次只能移动一个圆盘。
package hanoi;

/**
 * formula
 * T1 = 1
 * T2 = 3
 * Tn = 2T(n-2) + 3
 * 
 * closed form:
 * 
 * 
 * @author yaoh
 *
 */
public class FourHanoi {
	
	public static int count = 0;
	
	public static void hanoi(String a, String b, String c, String d, int n) {
		if(n == 1) {
			System.out.println("Step " + ++count + ": move " + n + " from " + a + " to " + d);
		}else if(n == 2) {
			System.out.println("Step " + ++count + ": move " + (n - 1) + " from " + a + " to " + b);
			System.out.println("Step " + ++count + ": move " + n + " from " + a + " to " + d);
			System.out.println("Step " + ++count + ": move " + (n - 1) + " from " + b + " to " + d);
		}
		else {
			hanoi(a, b, d, c, n - 2);
			
			System.out.println("Step " + ++count + ": move " + (n - 1) + " from " + a + " to " + b);
			System.out.println("Step " + ++count + ": move " + n + " from " + a + " to " + d);
			System.out.println("Step " + ++count + ": move " + (n - 1) + " from " + b + " to " + d);
			
			hanoi(c, a, b, d, n - 2);
		}
	}
	
	public static void main(String[] args) {
		hanoi("a", "b", "c", "d", 6);
		
		System.out.println("Overall steps: " + count);
	}
}

3. 有三根柱子,在一根柱子上从下往上按大小顺序摞着m片圆盘, 另一根柱子上从下往上按大小顺序摞着n片圆盘,要求把圆盘从下面开始按大小顺序重新摆放在最后一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。

4. 有三根柱子,在三根柱子上从下往上按大小顺序分别摞着m,n,l片圆盘, 要求把圆盘从下面开始按大小顺序重新摆放在最后一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。

最后两道题两个并做一个写,太jb复杂了,回头看看别人有没什么好办法
/*Problem Statement
     	There are three stacks of crates - two of them outside of the warehouse, and one inside the warehouse. 
     	We have a crane that can move one crate at a time, and we would like to move all of the crates to the stack inside the warehouse. 
     	A heavier crate can never be stacked on top of a lighter crate, and all three initial stacks obey that rule.
     	Create a class CraneWork that contains a method moves that is given int[]s stack1, stack2, and warehouse containing the initial three stacks, 
     	and returns the minimum number of moves required to move all the crates into the warehouse stack. 
     	The elements of stack1, stack2, and warehouse represent the weights of the crates and are given from top to bottom 
     	(and thus in non-decreasing order of weight).
     	
Definition
	Class: 	CraneWork
	Method: 	moves
	Parameters: 	int[], int[], int[]
	Returns: 	int
	Method signature: 	int moves(int[] stack1, int[] stack2, int[] warehouse)
	(be sure your method is public)

Constraints
 	stack1, stack2, and warehouse will each contain between 0 and 20 elements, inclusive.
 	The total number of elements in the three stacks will be between 1 and 20, inclusive.
 	Each element in the three stacks will be between 1 and 200, inclusive.
 	stack1, stack2, and warehouse will each be in non-decreasing order.

Examples

	0){3,50}   {}     {1,2,50,50,50}
	Returns: 12
	Move 3 to stack2, 1 to stack1, 
		2 to stack2, 1 to stack2, 
		50 to warehouse, 1 to warehouse, 
		2 to stack1, 1 to stack1, 
		3 to warehouse, 1 to stack2, 
		2 to warehouse, 1 to warehouse.

	1){50}    {50}    {10,20,30}
	Returns: 17
	Start by moving 50 from stack2 to stack1. 
	It then takes 7 moves to transfer the 10,20,30 
	to stack 2, 2 moves to transfer the 2 50's to the warehouse, 
	and 7 more to transfer the 10,20,30 to the warehouse.

	2){}      {}      {2,5,6,7}
	Returns: 0
	All the crates are already in the warehouse.

	3){1,2,3}  {}     {}
	Returns: 7
	Move 1 from stack1 to warehouse, 2 from stack1 to stack2, 
	1 from warehouse to stack2, 3 from stack1 to warehouse, 
	1 from stack2 to stack1, 2 from stack2 to warehouse, 1 from stack1 to warehouse.

	This problem statement is the exclusive and proprietary property of TopCoder, Inc. 
	Any unauthorized use or reproduction of this information without the prior written consent of TopCoder, Inc. 
	is strictly prohibited. (c)2003, TopCoder, Inc. All rights reserved. */

package cranework_2;

public class CraneWork {
	
  	public static void moves(int[] stack_1, int[] stack_2, int[] ware_house) throws Exception{
  		CrateStack stack1 = new CrateStack(stack_1);
  		CrateStack stack2 = new CrateStack(stack_2);
  		CrateStack warehouse = new CrateStack(ware_house);
  		
  		show(stack1, stack2, warehouse);
  		moves(stack1, 0, stack2, 0, warehouse, 0);  		
	}
  	
  	/**
  	 * @param stack1
  	 * @param cursor1
  	 * @param stack2
  	 * @param cursor2
  	 * @param stack3
  	 * @param cursor3
  	 * @throws Exception
  	 */
  	public static void moves(CrateStack stack1, int cursor1, CrateStack stack2, int cursor2, CrateStack stack3, int cursor3) throws Exception{
  		
  		if(cursor1 == stack1.root && cursor2 == stack2.root) return;
  		
  		if(cursor1 == stack1.root) {
  	  		if(cursor3 == stack3.root) {
  	  			moves(stack2, cursor2 + 1, stack3, stack3.root, stack1, stack1.root);
  	  			
  	  			stack3.pushCrate(stack2.popCrate());
  	  				
  	  			show(stack1, stack2, stack3);
  	  			
  	  			moves(stack1, cursor1, stack2, stack2.root, stack3, stack3.root);
  	  		} else if (stack2.getValue(cursor2) > stack3.getValue(cursor3)) {
				moves(stack2, cursor2 + 1, stack3, cursor3, stack1, stack1.root);

				stack3.pushCrate(stack2.popCrate());

				show(stack1, stack2, stack3);

				moves(stack1, cursor1, stack2, stack2.root, stack3, stack3.root);
  			}else {
  				cursor3 = stack3.find(stack2.getValue(cursor2));
  				
  				moves(stack2, cursor2 + 1, stack3, cursor3, stack1, stack1.root);
  				
  				stack3.pushCrate(stack2.popCrate());
  				
  				show(stack1, stack2, stack3);
				
  				moves(stack1, cursor1, stack2, stack2.root, stack3, stack3.root);
  			}
  		} else if(cursor2 == stack2.root) {	
  			if(cursor3 == stack3.root) {
  	  			moves(stack1, cursor1 + 1, stack3, stack3.root, stack2, stack2.root);
  	  				
  	  			stack3.pushCrate(stack1.popCrate());
  	  				
  	  			show(stack1, stack2, stack3);
  	  				
  	  			moves(stack2, cursor2, stack1, stack1.root, stack3, stack3.root);
  	  		} else if (stack1.getValue(cursor1) > stack3.getValue(cursor3)) {
  				moves(stack1, cursor1 + 1, stack3, cursor3, stack2, stack2.root);
  				
  				stack3.pushCrate(stack1.popCrate());
  				
  				show(stack1, stack2, stack3);
				
  				moves(stack2, cursor2, stack1, stack1.root, stack3, stack3.root);
  			}else {
  				cursor3 = stack3.find(stack1.getValue(cursor1));
  				
  				moves(stack1, cursor1 + 1, stack3, cursor3, stack2, stack2.root);
  				
  				stack3.pushCrate(stack1.popCrate());
  				
  				show(stack1, stack2, stack3);
				
  				moves(stack2, cursor2, stack1, stack1.root, stack3, stack3.root);
  			}
  		} else if(cursor3 == stack3.root) {
  			if (stack1.getValue(cursor1) > stack2.getValue(cursor2)) {
  				moves(stack1, cursor1 + 1, stack3, stack3.root, stack2, cursor2);
  				
  				stack3.pushCrate(stack1.popCrate());
  				
  				show(stack1, stack2, stack3);
  				
  				moves(stack2, cursor2, stack1, stack1.root, stack3, stack3.root);
  			} else {
  				moves(stack2, cursor2 + 1, stack3, stack3.root, stack1, cursor1);
  				
  				stack3.pushCrate(stack2.popCrate());
  				
  				show(stack1, stack2, stack3);
  				
  				moves(stack1, cursor1, stack2, stack2.root, stack3, stack3.root);
  			}
  		} else if (stack3.getValue(cursor3) > stack2.getValue(cursor2) && stack3.getValue(cursor3) > stack1.getValue(cursor1)) {
			if (stack1.getValue(cursor1) > stack2.getValue(cursor2)) {
				
				cursor3 = stack3.find(stack1.getValue(cursor1));
				
				moves(stack1, cursor1 + 1, stack3, cursor3, stack2, cursor2);
				
				stack3.pushCrate(stack1.popCrate());
				
				show(stack1, stack2, stack3);
				
				moves(stack2, cursor2, stack1, stack1.root, stack3, stack3.root);
			} else {
				cursor3 = stack3.find(stack2.getValue(cursor2));
				
				moves(stack2, cursor2 + 1, stack3, cursor3, stack1, cursor1);

				stack3.pushCrate(stack2.popCrate());

				show(stack1, stack2, stack3);
				
				moves(stack1, cursor1, stack2, stack2.root, stack3, stack3.root);
			}
		} else {
			if (stack1.getValue(cursor1) > stack2.getValue(cursor2)) {
				moves(stack1, cursor1 + 1, stack3, cursor3, stack2, cursor2);
				
				stack3.pushCrate(stack1.popCrate());
				
				show(stack1, stack2, stack3);
				
				moves(stack2, cursor2, stack1, stack1.root, stack3, stack3.root);
			}
			else {
				moves(stack2, cursor2 + 1, stack3, cursor3, stack1, cursor1);

				stack3.pushCrate(stack2.popCrate());

				show(stack1, stack2, stack3);

				moves(stack1, cursor1, stack2, stack2.root, stack3, stack3.root);
			}
		}
	}
  	
	public static void show(CrateStack stack1, CrateStack stack2, CrateStack stack3){
		System.out.println("Round:");
		stack1.showStack();
		stack2.showStack();
		stack3.showStack();
		//System.out.print("\n " + cursor1.weight + "   " + cursor2.weight + "   " +  cursor3.weight);
		System.out.println("\n");
	}
}

class CrateStack {
	
	private int[] stack = new int[20];
	
	public int root = 0;

	public CrateStack(int weight) {
		stack[0] = weight;
		root++;
	}
	
	public CrateStack(int[] array) {
		for(int i = 0; i < array.length; i++) {
			stack[i] = array[i];
		}
		root = array.length;
	}
	
	//Push a Value into Stack
	public void pushCrate(int value) {
		stack[root] = value;
		root++;
	}
	
	//Pop a Value into Stack
	public int popCrate() throws Exception{
		if(root != 0) {
			root--;
			int result = stack[root];
			stack[root] = 0;
			return result;
		}
		throw new NullPointerException();
	}
	
	
	public boolean isTop(int cursor) {
		if(cursor == root - 1) return true;
		return false;
	}
	
	public void showStack() {
		try {
			if (root == 0) {
				System.out.print("{}");
			} else {
				int temp = root - 1;
				System.out.print("{");
				while (temp >= 0) {
					System.out.print(stack[temp] + ",");
					temp--;
				}
				System.out.print("}");
			}
		} catch (Exception e) {
			//
		}
	}
	
	public int find (int temp) {
		int cursor = 0;
		if (temp != 0) {
			while(cursor != root) {
				if (stack[cursor] < temp) return cursor;
				cursor++;
			}
		}
		
		return root;
	}
	
	public int getValue(int index) {
		return stack[index];
	}
	
}





最近做了些思路上的转变,并对汉诺塔有了新的理解,回想之前的复杂汉诺塔的程序,觉得还是可以改进很多的。

package hanoi;

import java.util.Stack;

public class MultiHanoi {

	public static int count = 0;
	

	public static HanoiStack Largest(HanoiStack stackA, int locA, HanoiStack stackB, int locB, HanoiStack stackC, int locC) {
		if(stackA.get(locA) > stackB.get(locB) && stackA.get(locA) > stackC.get(locC)) return stackA;
		else if (stackB.get(locB) > stackA.get(locA) && stackB.get(locB) > stackC.get(locC)) return stackB;
		
		return stackC;
	}
	
	public static void multiHanoi(HanoiStack stackA, int locA,HanoiStack stackB, int locB, HanoiStack stackC, int locC) {
		if((stackA.size() == 0 || stackA.size() <= locA) && (stackB.size() == 0 || stackB.size() <= locB)) {
			return;
		} else if(stackA.size() == 0 || stackA.size() <= locA) {
			hanoi(stackB, locB, stackA, stackC);
		} else if(stackB.size() == 0 || stackB.size() <= locB) {
			hanoi(stackA, locA, stackB, stackC);
		} else {
			if(Largest(stackA, locA, stackB, locB, stackC, locC).name.equals(stackA.name)) {
				multiHanoi(stackA, locA + 1, stackC, locC, stackB, locB);
				int value = stackA.pop();
				stackC.push(value);
				System.out.println("Step " + ++count + ": move " + value + " from " + stackA.name + " to " + stackC.name);
				hanoi(stackB, locB, stackA, stackC);
			} else if(Largest(stackA, locA, stackB, locB, stackC, locC).name.equals(stackB.name)) {
				multiHanoi(stackB, locB + 1, stackC, locC, stackA, locA);
				int value = stackB.pop();
				stackC.push(value);
				System.out.println("Step " + ++count + ": move " + value + " from " + stackB.name + " to " + stackC.name);
				hanoi(stackA, locA, stackB, stackC);
			} else if(Largest(stackA, locA, stackB, locB, stackC, locC).name.equals(stackC.name)) {
				locC++;
				multiHanoi(stackA,locA, stackB, locB, stackC, locC);
			}
			
		}
		
	}
	
	public static void hanoi(HanoiStack sA, int locA, HanoiStack sB, HanoiStack sC) {
		if(sA.size() == locA + 1) {
			int value = sA.pop();
			sC.push(value);
			System.out.println("Step "+ ++count+ ": move "+value+" from "+sA.name+" to "+sC.name);
		} else {
			int locB = sB.size();
			
			hanoi(sA, locA + 1, sC, sB);
			
			int value = sA.pop();
			sC.push(value);
			System.out.println("Step "+ ++count+ ": move "+value+" from "+sA.name+" to "+sC.name);
			
			hanoi(sB, locB, sA, sC);
		}
		
		
	}
	
	public static void main(String[] args) {
		HanoiStack stackA = new HanoiStack("A");
		HanoiStack stackB = new HanoiStack("B");
		HanoiStack stackC = new HanoiStack("C");
		
		stackA.push(10);
		stackA.push(7);
		stackA.push(6);
		stackA.push(5);
		stackA.push(1);

		stackB.push(9);
		stackB.push(8);
		stackB.push(4);
		stackB.push(3);
		stackB.push(2);
		
		multiHanoi(stackA, 0, stackB, 0, stackC, 0);
		
		System.out.println("Overall steps: " + count);
	}
}

class HanoiStack {
	
	public String name;
	
	private Stack<Integer> stack;
	
	
	public HanoiStack(String name) {
		stack = new Stack<Integer>();
		
		this.name = name;
	}
	
	public void push(int val) {
		stack.push(val);
	}
	
	public int pop() {
		if(stack.isEmpty()) return 0;
		
		return stack.pop();
	}
	
	public int size() {
		return stack.size();
	}
	
	public int get(int loc) {
		if(loc >= stack.size()) return Integer.MIN_VALUE;
		return stack.get(loc);
	}
}


现在看起来比上一个程序简单明了了许多,但是其实步数是一样的,性能并没有增加。

不过基本上这已经算是最优的解法了。
分享到:
评论

相关推荐

    C经典算法之三色汉诺塔

    三色汉诺塔是一种基于传统汉诺塔问题的变种。在传统的汉诺塔问题中,玩家需要将一叠不同大小的盘子从一个柱子移动到另一个柱子上,中间可以使用第三个柱子作为辅助。移动过程中必须遵循以下规则:每次只能移动一个...

    汉诺塔问题汉诺塔问题

    Java-数据结构 - Hangzhou Dianzi University Online Judge Forum HDOJ ACM ICPC HDU - powered by phpwind_net.htm"可能是杭州电子科技大学在线评测系统的题目页面,其中包含了汉诺塔问题的一个变种——汉诺塔III。...

    汉诺塔问题

    此外,对汉诺塔问题的条件进行修改,如允许某些特殊情况下的大盘子位于小盘子上方,可以生成新的变种问题,这些变种可能需要不同的算法来解决。 在分析汉诺塔问题时,通常会关注算法的时间复杂度和空间复杂度。递归...

    JAVA经典算法.pdf

    综合以上内容,可以总结出递归算法在解决汉诺塔问题中的重要性,动态规划在处理背包问题中的应用,以及对于汉诺塔变种问题中额外的约束条件处理。这些算法是计算机科学基础中的经典问题,广泛应用于算法学习和实际...

    hdu 汉诺塔

    ### ACM HDU 汉诺塔 递归练习 #### 概述 汉诺塔(Hanoi Tower)问题是一个经典的递归算法示例,在计算机科学...通过对汉诺塔问题及其变种的研究和练习,不仅可以加深对递归算法的理解,还能培养解决实际问题的能力。

    分治法实现双色汉诺塔

    在这个变种的双色汉诺塔问题中,除了大小规则外,还添加了颜色规则,即不允许相同颜色的圆盘叠在一起。 3. **移动规则**: - 规则(1):每次只能移动1个圆盘。 - 规则(2):任何时候都不能将较大的圆盘压在较小的...

    PUZZLE15_dfs_C++求解15拼图问题_bfs_

    15拼图问题,也被称为15滑块游戏或汉诺塔变种,是一个经典的滑动拼图游戏。在这个游戏中,一个4x4的网格中有一片空位,其余15片数字瓷砖(1到15)被打乱排列。目标是通过移动瓷砖,将它们按顺序排列在网格上。在这个...

    Hanoi问题 1

    总结来说,汉诺塔问题的变种引入了 M 值,使得问题的解决方案更加复杂。解决这类问题需要理解递归算法,可能还需要动态规划或贪心策略,以及有效的分组和移动策略。对于给定的输入 N 和 M,我们寻求的是能够将所有...

    面向对象课程设计汉若塔实习报告

    在整个过程中,抽象体现在将问题抽象为对象和方法,分类体现在将问题分解为不同步骤,而继承和多态可能体现在扩展算法以适应不同变种的汉诺塔问题,例如多个圆盘大小相同的场景。通过这样的设计,学生能够深入理解...

    经典算法(C语言).pdf

    从提供的文件内容中,我们可以提取到几个经典的算法问题以及它们的C语言实现,包括汉诺塔问题、斐波那契数列求解、组合数计算以及荷兰国旗问题。以下是对这些算法知识点的详细阐述: 1. 汉诺塔问题(Towers of ...

    湖北省黄冈市罗田县2020届高三数学上学期11月月考试题文

    10. 汉诺塔游戏:第十题是汉诺塔游戏的变种,涉及到递推问题。根据规则,最少次数为2^5 - 1 = 31次,因此答案是B。 11. 导数与不等式:第十一题考察函数的导数与不等式的解。由题意可得,当x&gt;1时,f'(x)&gt;0,因此f(x...

    轻松学C语言 C语言程序设计教程 C语言入门教程 第16章 经典例题分析 共39页.pptx

    在本章《轻松学C语言 C语言程序设计教程 C语言入门教程 第16章 经典例题分析》中,我们将深入探讨三个经典的C语言编程问题:八皇后问题、汉诺塔问题和猴子选大王问题,以及如何利用C语言解决这些问题的算法设计。...

    stack.pptx

    汉诺塔问题的不同变种可以通过调整初始状态和目标状态来实现。 ##### 4. 开关盒布线判断 该问题是关于平面电路板上的布线问题,给定一对针脚,判断是否可以在不相交的情况下完成布线。 - 从起点开始,按顺时针...

    分酒_java_算法_

    分酒问题是计算机科学中一种经典的递归算法问题,与汉诺塔问题有着密切的联系。在汉诺塔问题中,我们需要将N个盘子从一个柱子移动到另一个柱子,遵循每次只能移动一个盘子且大盘子不能放在小盘子上的规则。而在分酒...

    Mazes for Programmers - Code Your Own Twisty Little Passages

    6. **汉诺塔算法**:在某些迷宫构造中,可以应用汉诺塔问题的思路,通过递归地移动“盘子”来生成复杂路径。 7. **回溯法**:当一条路径无法继续时,回溯到上一步并尝试其他分支。这种策略在解决迷宫求解问题时十分...

    leetcode分类-LeetCode:LeetCode在线裁判C++

    leetcode 分类 LeetCode 152/152 ToDoList -1。 delete int,double最大值 throw ...18.汉诺塔 排序堆的建立..... 推排序 相当于优先队列 19.图的算法 kruskal prim dijstria flordy 似乎都拼错了。

    SGU题库整合 Volume (200 - 299) pdf版

    - **问题描述**: 探讨汉诺塔问题的变种,比如增加盘子的数量或改变移动规则等。 - **解决方案**: 1. **递归算法**: 利用递归的思想解决问题。 2. **优化策略**: 针对不同的变种提出相应的优化方案。 - **实际意义*...

    DailyPractice

    汉诺塔;青蛙跳台;变种水仙花打印 2020_11_17:三角形边长判断并输出三角形类型;计算BMI确定健康状况;计算整数多重最大连续子序列和;字符串匹配问题;计算非负整数的二进制数值(不带前导0);计算非负整数的二...

    算法-分治- 三分法(包含源程序).rar

    分治法的经典应用包括:快速排序、归并排序、大整数乘法(Karatsuba算法)、Strassen矩阵乘法、汉诺塔问题等。 **三分法详解:** 三分法是分治法的一个变种,主要应用于查找问题,例如在有序数组中查找特定元素。...

    C数据结构与算法的源代码

    3. 递归算法:是一种在函数调用自身的技术,常用于解决树形结构问题,如斐波那契数列、汉诺塔问题、图的遍历等。 4. 动态规划:通过构建子问题的最优解来找到原问题的最优解,例如背包问题、最长公共子序列等。 5. ...

Global site tag (gtag.js) - Google Analytics