问题:
迷宫问题:起始是迷宫的左上角(0,0),目的位置是迷宫的右下角(6,12)。其中1代表通道,0代表墙壁。只允许进行垂直或者水平移动,禁止对角线移动。
例子:
1 1 1 0 1 1 0 0 0 1 1 1 1
1 0 1 1 1 0 1 1 1 1 1 0 1
1 0 0 0 1 0 1 0 1 0 1 0 1
1 0 0 0 1 1 1 0 1 0 1 1 1
1 1 1 1 1 0 0 0 0 1 0 0 0
0 0 0 0 1 0 0 0 0 0 0 0 0
0 0 0 0 1 1 1 1 1 1 1 1 1
分析:
从(0,0)开始往上下左右试探:
- 如果选择的位置是目的位置,成功结束。
- 如果选择的位置是有效位置,但不是目的位置,以此位置继续上下左右试探下去。
- 没有一个有效位置,说明无法到达 目的位置。
代码编写:
Position类:位置类
Maze:迷宫处理类
MazeIterator:自定义迭代类,遍历上下左右相邻点
package com.kzl.backtrack;
/**
* 位置类
*/
public class Position {
private int row;
private int column;
public Position() {
row = 0;
column = 0;
}
public Position(int row, int column) {
this.row = row;
this.column = column;
}
public int getRow() {
return row;
}
public int getColumn() {
return column;
}
}
package com.kzl.backtrack;
import java.util.Iterator;
public class Maze {
private static final byte WALL = 0; // 墙
private static final byte CORRIDOR = 1; // 通道
private static final byte PATH = 9; // 路径通过的位置
private static final byte TRIED = 2; // 死胡同
public Position finish;
public byte[][] grid;
public Maze(byte[][] grid, Position finish) {
this.grid = grid;
this.finish = finish;
}
// 判断位置是否有效
public boolean valid(Position pos) {
if (pos.getRow() >= 0 && pos.getRow() < grid.length &&
pos.getColumn() >= 0 && pos.getColumn() < grid[0].length &&
grid[pos.getRow()][pos.getColumn()] == CORRIDOR) {
return true;
}
return false;
}
// 记录路径通过的位置
public void record(Position pos) {
grid[pos.getRow()][pos.getColumn()] = PATH;
}
// 判断是否到达目的地
public boolean done(Position pos) {
return pos.getRow() == finish.getRow() &&
pos.getColumn() == finish.getColumn();
}
// 如果走不通,就回退,并把此位置置为死胡同
public void undo(Position pos) {
grid[pos.getRow()][pos.getColumn()] = TRIED;
}
// 自定义迭代方法
public Iterator iterator(Position pos) {
return new MazeIterator(pos);
}
// 回溯策略的主要步骤
public boolean tryToSolve(Position pos) {
boolean success = false;
Iterator it = iterator(pos);
// 没有到达目的地,在这个位置的上下左右试探
while (!success && it.hasNext()) {
pos = (Position)it.next();
// 如果该位置有效
if (valid(pos)) {
// 记录该位置
record(pos);
// 如果是目的地,结束
if (done(pos)) {
success = true;
} else {
// 如果是有效位置,但不是目的地,继续调用tryToSolve方法
success = tryToSolve(pos);
// 如果走不通
if (!success) {
// 该位置为死胡同
undo(pos);
}
}
}
}
return success;
}
}
package com.kzl.backtrack;
import java.util.Iterator;
public class MazeIterator implements Iterator {
private int row;
private int column;
private int count = 0;
public MazeIterator(Position pos) {
this.row = pos.getRow();
this.column = pos.getColumn();
}
@Override
public boolean hasNext() {
return count < 4;
}
@Override
public Object next() {
Position next = null;
// 遍历4个方向
switch (count++) {
case 0:
next = new Position(row - 1, column);
break;
case 1:
next = new Position(row, column - 1);
break;
case 2:
next = new Position(row + 1, column);
break;
case 3:
next = new Position(row, column + 1);
}
return next;
}
@Override
public void remove() {
}
}
package com.kzl.backtrack;
public class Main {
public static void main(String[] args) {
byte[][] grid = {
{1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1},
{1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1},
{1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1},
{1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1},
{1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0},
{0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1},
};
Position start = new Position();
Position finish = new Position(6, 12);
process(grid, start, finish);
}
public static void process(byte[][] grid, Position start, Position finish) {
Maze maze = new Maze(grid, finish);
if (!maze.valid(start) || !(maze.valid(finish))) {
System.out.println("failure");
} else {
maze.record(start);
if (maze.done(start) || maze.tryToSolve(start)) {
System.out.println("success");
} else {
maze.undo(start);
System.out.println("failure");
}
}
for (byte[] b : grid) {
for (byte t : b) {
System.out.print(t + " ");
}
System.out.println();
}
}
}