Hanoi拓展(java)

本文介绍了一种汉诺塔问题的变种,通过使用三个集合来跟踪不同柱子上的圆盘状态,并通过递归算法找出特定状态在最优路径中的位置。适用于理解汉诺塔算法及其变体。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、题意:

题目描述

有一个int数组arr其中只含有1、2和3,分别代表所有圆盘目前的状态,1代表左柱,2代表中柱,3代表右柱,arr[i]的值代表第i+1个圆盘的位置。比如,arr=[3,3,2,1],代表第1个圆盘在右柱上、第2个圆盘在右柱上、第3个圆盘在中柱上、第4个圆盘在左柱上。如果arr代表的状态是最优移动轨迹过程中出现的状态,返回arr这种状态是最优移动轨迹中的第几个状态。如果arr代表的状态不是最优移动轨迹过程中出现的状态,则返回-1。

给定一个int数组arr及数组的大小n,含义如题所述,请返回一个int,代表所求的结果。

测试样例:
[3,3]
返回:3


2、code:

package schooloffer;

import java.util.HashSet;
import java.util.Set;

/**
 * Created by caoxiaohong on 17/10/25.
 * 有一个int数组arr其中只含有1、2和3,分别代表所有圆盘目前的状态,1代表左柱,2代表中柱,3代表右柱....
 * 算法思想:其实这道题主要算法思想还是和基本Hanoi一样,就是多添加了几个状态left,right,mid,用来存放移动中的中间状态,
 * 以方便查看每次移动结束后,是否已经达到目标状态.
 */
public class Hanoi2 {
    Set<Integer> left=new HashSet<Integer>();//存放:第一根柱子上面各个盘子的编号
    Set<Integer> mid=new HashSet<Integer>();//存放:第二根竹子上面各个盘子的编号
    Set<Integer> right=new HashSet<Integer>();//存放:第三根柱子上面各个盘子的编号
    int isFind=0;//标志:找到时,移动次数是第几次
    int times=0;//递归次数:为isFind赋值

    public int chkStep(int[] arr, int n) {
        // write code here
        if(n==1 && arr[0]==1)
            return 0;
        if(n==1 && (arr[0]==2 || arr[0]==3))
            return 1;
        //初始化
        int count=n;
        while (count>0)
            left.add(count--);
        //调用递归算法
        helper(n,1,3,2,arr);
        return isFind;
    }

    /**
     * 递归移动
     * @param n 一个n个盘子
     * @param from 盘子初始位置
     * @param to 盘子要被移动到的位置
     * @param depend 移动过程中的辅助位置
     * @param arr 目标状态
     */
    private void helper(int n,int from,int to ,int depend,int[] arr){
        if(n==1){
            move(1,from,to,arr);
        }else{
            helper(n-1,from,depend,to,arr);
            move(n,from,to,arr);
            helper(n-1,depend,to,from,arr);
        }
    }

    /**
     * 移动一次
     * @param idx 当前被移动的盘子的编号
     * @param from 盘子的初始位置
     * @param to 盘子要被移动到的位置
     * @param arr 目标状态
     */
    private void move(int idx,int from,int to,int[] arr){
        if(from==1)
            left.remove(idx);
        else if(from==2)
            mid.remove(idx);
        else if(from==3)
            right.remove(idx);

        if(to==1)
            left.add(idx);
        else if(to==2)
            mid.add(idx);
        else if(to==3)
            right.add(idx);
        //是否和arr一致
        int i;
        for(i=0;i<arr.length;i++){
            if(arr[i]==1 && !left.contains(i+1))
                break;
            else if(arr[i]==2 && !mid.contains(i+1))
                break;
            else if(arr[i]==3 && !right.contains(i+1))
                break;
        }
        times++;
        if(i==arr.length)
            isFind=times;
    }

    //test code
    public static void main(String[] args) {
        Hanoi2 t=new Hanoi2();
        int[] a={3};
        System.out.println(t.chkStep(a,1));
    }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值