通过宽度优先,深度优先,A*来求解8数码难题(滑动谜题)(Java实现)
1. 要求
- 初始状态以及目标状态如下图所示。
- 输出完整的从初始状态到目标状态的Action序列。
- 对比三种算法的时间、空间消耗。
2. 设计思路
(1) 将该“棋盘”抽象为一个二维数组 int[][] state ,空的位置当作是 数字0 ,将二维矩阵转换为String(这样处理有利于比较和存储,但是String类型会消耗内存空间),那么例如:
初始状态可以定义为 String startstring =“724506831”
目标状态可以定位为 String goalstate = “012345678”
(2) 可以将该“棋盘”的每一个状态看作是一个树节点 **Node** ,每次移动 **Action** 后产生一个新的状态,每次移动可以看作是二维数组中某个数与0交换位置。
(3) 每次交换前的节点都会被保存在一个集合容器中(**栈或队列**)
并与目标状态进行比较,若相同则输出完整的从初始状态到目标状态的Action序列,若不同则保存在该集合容器中(保存的状态不能重复,也需要比较)。这样循环实现直到遍历完所有状态。
(4) 与0交换的某个数即方向定义为:
int[][] DIRECTIONS = {
{
0, -1 }, {
-1, 0 }, {
0, 1 }, {
1, 0 } };
即相当于以****“0”为中心画“十”字****,实现:****列或行+1或-1****。
(5) 移动的方式由不同算法实现,如下:
3. 实现
关于算法的消耗时间和内存,在程序内用以下实现:
Runtime r = Runtime.getRuntime();
r.gc();
// 主方法开始运行的时间
long startTime = System.currentTimeMillis();
// 主方法开始时的剩余内存
long startMem = r.freeMemory();
//********************** TODO here ********************
//********************** TODO here ********************
// 主方法结束的时间
long endTime = System.currentTimeMillis();
// 主方法结束剩余内存
long endMem = r.freeMemory();
System.out.println("程序用时: " + (endTime - startTime) + " ms");
System.out.println("程序消耗内存: " + (startMem - endMem) / 1024 + " Kb");
BFS(广度优先搜索)
-
从初始状态节点开始,每一个节点都对0进行四个方向的移动,得到四个新的节点,对新节点重复操作
-
对新的节点判别:
(1) 若之前没有访问过,就存入队列;
(2) 若与目标状态相同,就停止循环输出该节点及所有移动action。
-
若已经遍历了所有状态节点没有得到目标状态,就输出无法到达目标状态。
-
优先度如图:
节点类
package exp1.expbfs;
import java.util.Arrays;
/**
* 此类为封装的节点类
*
* @author
*
*/
public class NodeBFS {
//0所在位置
int zero_row,zero_column;
int[][] state;
//将数组转化为String(或者可以重写toString方法)
String statestring;
//记录父节点
NodeBFS father;
//记录移动的次数
int counts;
/**
*
* @param father 父节点
* @param state 状态
* @param zero_row 0所在的行
* @param zero_column 0所在的列
*/
public NodeBFS(NodeBFS father,int[][] state,int zero_row,int zero_column) {
this.father=father;
this.state=state;
this.zero_row=zero_row;
this.zero_column=zero_column;
this.statestring=Arrays.deepToString(state);
if(null==this.father)
this.counts=0;
else
this.counts=this.father.counts+1;
}
}
package exp1.expbfs;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Set;
public class BFS {
// 初始状态 START_STATE
// public static final int[][] START_STATE = { {3 ,1, 2 }, {4 , 0, 5}, { 6, 7,8 } };
public static final int[][] START_STATE = {
{
7 ,2, 4 }, {
5, 0, 6}, {
8, 3,