今天刷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);
}
}