区块世界问题

x33g5p2x  于2022-03-23 转载在 其他  
字(3.3k)|赞(0)|评价(0)|浏览(305)

一 问题描述

在早期的人工智能规划和机器人研究中使用了一个区块世界,在这个世界中,机器人手臂执行涉及区块操作的任务。问题是解析一系列命令,这些命令知道机器人手臂如何操作平板上的块。最初,有 n 个区块(编号从 0 到 n~1),如下图所示。

命令如下:

move a onto b:把 a 和 b 上方的块全部放回初始位置,然后把 a 放到 b 上方。

move a over b:把 a 上方的块全部放回初始位置,然后把 a 放到 b 所在块堆的最上方。

pile a onto b:把 b 上方的块全部放回初始位置,然后把 a 和 a 上方所有块整体放到 b 上方。

pile a over b:把 a 和 a 上方所有块整体放到 b 所在块堆的最上方。

quit:结束标志。

任何 a = b 或 a 和 b 在同一堆块中的命令都是非法命令。所有非法命令都应被忽略。

输入:输入的第行为整数 n,表示区块世界中的块数。后面是一系列块命令,每行一个命令。在遇到 quit 命令之前,程序应该出来所有命令。所有命令都将采用上面指定的格式,不会有语法错误的命令。

输出:输出应该包含区块世界的最终状态。每一个区块后面都有一个冒号。如果上面至少有一个块,则冒号后面必须跟一个空格,后面跟一个显示位置的块列表,每个块号与块号之间用空格隔开。

输入样例
10

move 9 onto 1

move 8 over 1

move 7 over 1

move 6 over 1

pile 8 over 6

pile 8 over 5

move 2 over 1

move 4 over 9

quit

输出样例

0:0

1:1 9 2 4

2:

3:3

4:

5:5 8 7 6

6:

7:

8:

9:

二 思路

初始时从左到右有 n 个块,编号从 0 到 n-1,要求实现一些操作。通过这些操作可以归纳总结出以下规律。

move:将 a 上方的块全部放回初始位置。

noto:将 b 上方的块全部放回初始位置。

公共操作:将 a 和 a 上方的所有块整体放到 b 所在块堆的最上方。

而实际上,前两种可以算一个操作:将 a 或 b 上方的块全部放回初始位置,简称归位。将 a 和 a 上方的所有块整体放到 b 所在块堆的最上方,简称移动。

只需要通过判断执行归位和移动操作就可以了。

三 算法设计

1 读取操作命令 s1,如果 s1="quit",则结束;否则执行下面两步。

2 读入操作命令 a s2 b,如果 s1="move",则 a 归位;如果 s2="onto",则 b 归位。

3 执行移动操作,即将 a 和 a 上方所有的块整体放到 b 所在堆块的最上方。

四 归位操作

要想使 a 上方的所有块归位,则首先要找到 a 所在的堆块,并知道 a 在堆块中的位置(高度),然后才能将 a 上方的所有块归位。

例如,将 8 上方所有块归位。首先查找 8 所在的堆块为1,8所在堆块的高度为2,然后将 1 号块堆大于 2 的所有块放回原来的位置。

五 移动操作

要想让 a 和 a 上方所有块整体放到 b 所在块的最上方,则首先要找到 a 和 b 所在的块堆,如果 a、b 所在块堆一样,则什么都不做。否则,将 a 块堆中高度大于或等于 h(a的高度)的所有块移动到 b 所在块堆的上方。

例如,将 8 和 8 上方所有块整体放到 9 所在块堆的最上方。首先查找到 8 所在的块堆为 5 号,9 所在的块堆为 1 号,8 所在的块堆的高度为 1,然后将 5 号块堆高度大于或等于 1 的所有块放到 1 号块堆的上方。

六 图解

初始值:

1 move 9 onto 1

2 move 8 over 1

3 move 7 over 1

4 move 6 over 1

5 pile 8 over 6

什么都不做。

6 pile 8 over 5

7 move 2 over 1

8 move 4 over 9

9 quit:结束

10 从左到右、从下到上输出每个位置的块编号。

七 实现

  1. package vector;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. import java.util.Scanner;
  5. import java.util.Vector;
  6. class Pos {
  7. private Integer p;
  8. private Integer h;
  9. public Integer getP() {
  10. return p;
  11. }
  12. public void setP(Integer p) {
  13. this.p = p;
  14. }
  15. public Integer getH() {
  16. return h;
  17. }
  18. public void setH(Integer h) {
  19. this.h = h;
  20. }
  21. public Pos(Integer p, Integer h) {
  22. this.p = p;
  23. this.h = h;
  24. }
  25. }
  26. public class BlockTest {
  27. // 构造队列
  28. private static List<Vector<Integer>> blocks = new ArrayList<>();
  29. // 多少个块
  30. private static int n = 0;
  31. // 找位置
  32. static void loc(int x, Pos pos) {
  33. for (int i = 0; i < n; i++) {
  34. for (int j = 0; j < blocks.get(i).size(); j++) {
  35. if (blocks.get(i).get(j) == x) {
  36. pos.setP(i);
  37. pos.setH(j);
  38. }
  39. }
  40. }
  41. }
  42. // 将p块堆高度大于 h 的所有块归位
  43. static void goBack(int p, int h) {
  44. for (int i = h + 1; i < blocks.get(p).size(); i++) {
  45. int k = blocks.get(p).get(i);
  46. blocks.get(k).addElement(k);
  47. }
  48. blocks.get(p).setSize(h + 1);
  49. }
  50. // 将 p 块堆高度大于或等于 h 的所有块都移动到 q 块堆的上方
  51. static void moveAll(int p, int h, int q) {
  52. for (int i = h; i < blocks.get(p).size(); i++) {
  53. int k = blocks.get(p).get(i);
  54. blocks.get(q).addElement(k);
  55. }
  56. blocks.get(p).setSize(h);
  57. }
  58. public static void main(String[] args) {
  59. // 初始化
  60. for (int i = 0; i <= 30; i++) {
  61. blocks.add(new Vector());
  62. }
  63. Scanner input = new Scanner(System.in);
  64. n = input.nextInt();
  65. for (int i = 0; i < n; i++) {
  66. blocks.get(i).addElement(i);
  67. }
  68. int a;
  69. int b;
  70. String s1;
  71. String s2;
  72. while (true) {
  73. s1 = input.next();
  74. if (s1.equals("quit")) {
  75. break;
  76. }
  77. a = input.nextInt();
  78. s2 = input.next();
  79. b = input.nextInt();
  80. Integer ap = 0;
  81. Integer ah = 0;
  82. Integer bp = 0;
  83. Integer bh = 0;
  84. Pos pos1 = new Pos(ap, ah);
  85. loc(a, pos1);
  86. Pos pos2 = new Pos(bp, bh);
  87. loc(b, pos2);
  88. if (pos1.getP() == pos2.getP()) {
  89. continue;
  90. }
  91. if (s1.equals("move")) {
  92. goBack(pos1.getP(), pos1.getH());
  93. }
  94. if (s2.equals("onto")) {
  95. goBack(pos2.getP(), pos2.getH());
  96. }
  97. moveAll(pos1.getP(), pos1.getH(), pos2.getP());
  98. }
  99. for (int i = 0; i < n; i++) {
  100. System.out.print(i + ":");
  101. for (int j = 0; j < blocks.get(i).size(); j++) {
  102. System.out.print(" " + blocks.get(i).get(j));
  103. }
  104. System.out.println();
  105. }
  106. }
  107. }

八 测试

绿色为输入,白色为输出

相关文章