如何利用Java递归解决“九连环”公式

在之前有写到过一点点有关递归的东西点击打开链接,然后想到小时候自己玩的一个玩具——九连环。小时候自己曾经一边玩一边用笔记下来解开这个东西的公式,那是十几年前的事情了。前两天突然想起来,九连环的基本操作就是一个递归,一个感觉起来非常标准的递归过程。

九连环的玩法规则用一句话来概括就是:如果你想要卸掉某一环或者装上某一环,只需要保留这一环前面一环,再之前所有的环都卸掉。(例如你想要卸掉或者装上第9环,那么保留第8环,第8环之前的所有的环都卸掉)其中第一环可以直接卸掉。(其实第一第二这两环可以一起装上一起卸掉,我们在逻辑上只是规定第一环可以自由移动)

那么按照递归的思想来实现这个问题,还是比较简单的。与之前提到的不同的是:这次对于某一环的操作不是一种,牵扯到装上和卸掉两种基本操作,所以针对九连环要设置一个标记状态——state:九连环在上,state=1;九连环在下,state=0 。这个在Node类中实现。(如同c++中的struct)

其中num属性表示环号,state表示环的状态。

第二个需要准备的就是利用ArrayList实现的一个栈,来将所有state=1的环压入栈中。九连环规则中要求:要想对某一环进行操作,要保证这一环的前一环state=1 且在栈顶。

第三个就是操作过程move,根据state的不同,设置move操作不同。

准备条件做好了,就是要设计递归实现了。首先写一下设计的思想(伪代码)

play(n){
	n=1://基础情形
		move(n);
	n>1:
		while(!deal)//没有完成对这一环的操作
		{
			(n-1).state=1://前一环在上
				stack.pop=n-1://前一环为栈顶
					move(n);
					deal=true;
					stack.remove(size-2);//将第n环从栈中移走(并不是仅能够在栈顶进行操作的完全意义上的栈)
				stack.pop!=n-1://前一环不是栈顶
					for(i=n-2 to 1)
						find index where index.state!=0;//从大到小找到第一个在上的环(栈中在第n-1环之前的环)
					play(index);//将这个发现的在上的环移走

			(n-1).state=0://前一环不在上
				play(n-1);//执行对前一环的操作(即如果前一环在上就移走,如果不在上就装上)
		}
}

这个只是将某一环移走或者装上的操作,如果将整个游戏都结束,在执行函数的时候需要从高到低依次移走这些环。(见main函数)。main函数中还需对九连环的初始状态以及栈的初始状态进行初始化。(见main函数)

运行结果如下:(四个环)

具体实现,直接贴代码:

import java.util.*;
public class NC {

	public static void move(Node node) {
		if(node.state==1)
			System.out.println("down "+node.num);
		else
			System.out.println("up "+node.num);
	}

	public void play(Node[]node,ArrayList<Node> list,int n) {
		boolean deal=false;

		if(n==1) {
			if(node[n].state==1)
			{
				move(node[n]);// move the 1st;
				node[n].state=0;
				list.remove(list.size()-1);
			}
			else
			{
				move(node[n]);
				node[n].state=1;
				list.add(node[n]);
			}
		}
		else {
			while(!deal)
			{
				if(node[n-1].state==1) {//前一环在上
					if(list.get(list.size()-1).num==n-1)//前一环为栈顶
					{
						if(node[n].state==1)
						{
							move(node[n]);
							node[n].state=0;
							deal=true;
							list.remove(list.size()-2);
						}
						else
						{
							move(node[n]);
							node[n].state=1;
							deal=true;
							list.add(list.size()-1,node[n]);
						}
					}
					else//前一环在上,但是前一环不是栈顶
					{
						int index=1;
						for(int i=n-2;i>0;i--)//找到前一环之前的所有在上的环中最大的一个。
						{
							if(node[i].state==1) {
								index=i;
								break;
							}
						}
						play(node,list,index);//将前一环之前的在上的最大的一环移走
					}
				}
				//-------------------------------------------------------------------------
				else if(node[n-1].state==0) {//前一环不在上

					play(node,list,n-1);
			}
		}
	}

	}
	public static void main (String[]args) {
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt();
		Node []node= new Node[n+1];
		for(int i=1;i<n+1;i++)
			node[i]=new Node(i,1);
		ArrayList<Node> list= new ArrayList();
		for(int j=n;j>0;j--)
			list.add(node[j]);
		NC nc= new NC();
		for(int t=n;t>0;t--)
			nc.play(node, list,t);
	}
}

class Node{
	int num;
	int state;
	public Node(int num,int state) {
		this.num=num;
		this.state=state;
	}
}

总结

到此这篇关于如何利用Java递归解决“九连环”公式的文章就介绍到这了,更多相关Java递归“九连环”公式内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • java 用递归获取一个目录下的所有文件路径的小例子

    复制代码 代码如下: private List<String> ergodic(File file,List<String> resultFileName){        File[] files = file.listFiles();        if(files==null)return resultFileName;// 判断目录下是不是空的        for (File f : files) {            if(f.isDirectory()){// 判

  • java递归菜单树转换成pojo对象

    复制代码 代码如下: package com.cjonline.foundation.authority.pojo;import java.util.ArrayList;import java.util.Collections;import java.util.Iterator;import java.util.List;import org.apache.log4j.Logger;import com.cjonline.foundation.util.CheckNullEmpty;/** *

  • Java递归算法经典实例(经典兔子问题)

    题目:古典问题:3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? 分析:首先我们要明白题目的意思指的是每个月的兔子总对数:假设将兔子分为小中大三种,兔子从出生后三个月后每个月就会生出一对兔子, 那么我们假定第一个月的兔子为小兔子,第二个月为中兔子,第三个月之后就为大兔子,那么第一个月分别有1.0.0,第二个月分别为0.1.0, 第三个月分别为1.0.1,第四个月分别为,1.1.1,第五个月分别为2.1.2,第六个月分别为3.2.3,第

  • Java递归遍历树形结构

    废话不多说了,直接给大家贴代码,具体代码如下所示: //菜单树形结构 public JSONArray treeMenuList(JSONArray menuList, int parentId) { JSONArray childMenu = new JSONArray(); for (Object object : menuList) { JSONObject jsonMenu = JSONObject.fromObject(object); int menuId = jsonMenu.ge

  • Java无限级树(递归)超实用案例

    如下所示: @Override public String getEmployeeBysup(String employeeID) { String str=""; str = getEmployeeBysupSelas(employeeID, str); return str.substring(0, str.lastIndexOf(",")); } @Override public String getEmployeeBysupSelas(String empl

  • Java 跳出递归循环问题解决办法

    使用异常跳出循环 1.如果方法体内含有需要抛出异常的对象,让方法直接抛出异常,不要在方法体内捕获 public void xxxx() throws Exception 2.如果方法体内不含有需要抛出异常的对象 class Test { static class StopMsgException extends RuntimeException { } public static void main(String args[]) { try { run(0); } catch (StopMsgE

  • Java递归算法的使用分析

    递归算法是一种直接或者间接地调用自身的算法.在计算机编写程序中,递归算法对解决一大类问题是十分有效的,它往往使算法的描述简洁而且易于理解. 问题1:一列数的规则如下: 1.1.2.3.5.8.13.21.34 ,求第30位数是多少?使用递归实现 复制代码 代码如下: public class FibonacciSequence {    public static void main(String[] args){        System.out.println(Fribonacci(9))

  • Java算法之递归算法计算阶乘

    本文为大家分享的java算法计算阶乘,在学习Java课程时经常会遇到求阶乘问题,今天接跟大家一起探讨一下 代码如下: package com.xu.main; import java.util.Scanner; public class P9 { static long fact(int n) { if(n <= 1) { return 1; } else { return n * fact(n - 1); } } public static void main(String[] args) {

  • java 递归深入理解

    一.递归函数,通俗的说就是函数本身自己调用自己... 如:n!=n(n-1)! 你定义函数f(n)=nf(n-1) 而f(n-1)又是这个定义的函数..这就是递归 二.为什么要用递归:递归的目的是简化程序设计,使程序易读 三.递归的弊端:虽然非递归函数效率高,但较难编程,可读性较差.递归函数的缺点是增加了系统开销,也就是说,每递归一次,栈内存就多占用一截 四.递归的条件:需有完成任务的语句,需满足递归的要求(减小而不是发散) 五.递归进阶: 1.用递归算n的阶乘: 分析:n!=n*(n-1)*(

  • 快速排序算法原理及java递归实现

    快速排序 对冒泡排序的一种改进,若初始记录序列按关键字有序或基本有序,蜕化为冒泡排序.使用的是递归原理,在所有同数量级O(n longn) 的排序方法中,其平均性能最好.就平均时间而言,是目前被认为最好的一种内部排序方法 基本思想是:通过一躺排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列. 三个指针: 第一个指针称为pivotkey指针(枢轴),第二个指

随机推荐