初级算法:汉诺塔++

今天刷oj,遇见一个特别的汉诺塔问题,想了一天,写出来提交提示答案有误,我很郁闷,感觉写的没有问题,记录一下:
题目描述:
古老的汉诺塔问题是:用最少的步数将N个半径互不相等的圆盘从1号柱利用2号柱全部移动到3号柱,在移动过程中小盘永远在大盘上边。 现在再加上一个条件:不允许从1号柱直接把盘移动到3号柱, 也不允许从3号柱直接移动到1号柱。把盘按半径从小到大1——N进行编号。每种状态用N个整数表示, 第i个整数表示第i号盘所在的柱的编号。则N=2时的移动方案为(1,1)》(2,1)》(3,1)》(3,2)》(2,2)》(1,2)》(1,3)》(2,3) 》(3,3)初始状态为0步,变成求在某步数时的状态。
输入:
输入文件的第一行为整数T(1<=T<=100),表示输入数据的组数。接下来的T行,每行有两个整数N,M(1<=N<=19, 0<=M<=移动N个圆盘需要的次数)
输出:
输入文件一共T行对于每组输入数据,输出N个整数表示移动N个盘在M步时的状态,每两个数之间用一个空格隔开,行首和行末不要有多余的空格。

样例输入
3
2 0
2 1
2 2
样例输出
1 1
2 1
3 1

class Main {
	int step;
	int[] an = null;// 数组an表是第n步的状态(1,2,3);
	public static void main(String[] args) {
		// 输入部分
		// n表示盘子数量
		// m表示第几步
		//举例:n的2的过程(1,1)>(2,1)>(3,1)>(3,2)>(2,2)>(1,2)>(1,3)>(2,3)>(3,3)
		Scanner scanner = new Scanner(System.in);
		while (scanner.hasNext()) {
			int g = scanner.nextInt();
			int[][] data = new int[g][2];
			for (int i = 0; i < data.length; i++) {
				data[i][0] = scanner.nextInt();
				data[i][1] = scanner.nextInt();
			}
			// 输出部分 在第一个柱子上==1,在第二个柱子上==2,在第三个柱子上==3
			// 第一个盘子在哪个柱子上 第二个盘子在哪个柱子上 。。。。。。
			Main main = new Main();
			for (int i = 0; i < data.length; i++) {
				main.hanoi(data[i][0], data[i][1]);
			}
		}
	}

	private void hanoi(int i, int j) {
		step = 0;
		an = new int[i];
		for (int j2 = 0; j2 < an.length; j2++) {
			an[j2] = 1;
		}
		int a = 1;
		int b = 2;
		int c = 3;
		hanoi(i, a, b, c, j);
		for (int k = 0; k < an.length; k++) {
			if (k != an.length-1) {
				System.out.print(an[k] + " ");
			}else {
				System.out.print(an[k]);
			}
		}
		System.out.println();
	}

	private void hanoi(int i, int a, int b, int c, int j) {
		if (j == 0) {
			return;
		}
		if (i == 1) {
			move(i, a, b, j);
			move(i, b, c, j);
		} else {
			// 先把i-1个盘移动到c
			hanoi(i - 1, a, b, c, j);
			// 把a上最后一个移动到b
			move(i, a, b, j);
			// 把c上n-1的移动到a
			hanoi(i - 1, c, b, a, j);
			// 把b上的第n个移动到c
			move(i, b, c, j);
			// 把a上的n-1移到b
			hanoi(i - 1, a, b, c, j);
		}
	}

	private void move(int i, int a, int c, int j) {
		step++;
		if (step <= j) {
			an[i - 1] = c;
		}
//		  System.out.println("第"+(step)+"步移动盘"+i);
//		  System.out.println(a+"------------>"+c);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值