/*
Name:八数码(BFS+hash)
Actor:HT
Time:2015年6月22日
Error Reporte:
1.memcmp==0 代表匹配成功
2.memcpy(&+数组名,&+数组名,sizeof(数组名))
}
*/
#include"stdio.h"
#include"iostream"
#include"string.h"
using namespace std;
int map[1000000][9]; //看做无限大队列,其中每个元素都具有9个点,也就是说每个元素都是一张图
int goal[9];
int ans[1000000]; //答案,移动的步数,也就是深度,要对应每个元素
const int my[4] = { -1, 0, 1, 0 };
const int mx[4] = { 0, 1, 0, -1 }; //图上移动,这样很方便 分别为上右下左
const int mz[4] = { -3, 1, 3, -1 }; //串上移动
int hashhead[1000000] = { 0 }; //无数个空hash的表头,每个表头用于存储hash值一样的一类“map元素的序号”,下标是个hash值
int hashtable[1000000] = { 0 }; //无数个指向空的hash的指针,每个指针的下标和值都是“map元素的序号”;其实就是一个“序号”组成的链表
int fa[10000000] = { 0 }; //写着玩
void print(int m) //写着玩
{
int i;
for (i = 0; i < 9; i++)
{
cout <<map[m][i]<< " ";
if (i % 3 == 2) cout << endl;
}
}
int ahash(int rear)
{
int i,t=0;
for (i = 0; i < 9; i++) //hash数值设定,把所有的情况归结到几个hash值中
{
t *= 10;
t += map[rear][i];
t %= 1000000;
}
int rearlyhash = hashhead[t]; //找到这个hash数值应该对应的表的表头的真值(某个map元素的元素序号)
while (rearlyhash) //沿着这条链表开始搜索
{
if (memcmp(map[rearlyhash], map[rear], sizeof(map[rear])) == 0) return 0;
rearlyhash = hashtable[rearlyhash];
}
hashtable[rear] = hashhead[t]; //这个新来的序号(rear)的下一个指向表头
hashhead[t] = rear; //新来的序号成为了新的表头
return 1;
}
int bfs()
{
int zero,x,y; //零点在串的位置,以及在图的坐标
int i;
int front = 1, rear = 2;
ans[front] = 0;
while (front < rear)
{
if (memcmp(map[front],goal,sizeof(goal)) == 0) return front;
for (i = 0; i < 9; i++)
if (map[front][i] == 0)
{
zero = i;
break;
} //先找到0点
x = zero % 3; //分别为0 1 2
y = zero / 3; //分别为0 1 2
for (i = 0; i < 4; i++)
{
int newx = x + mx[i], newy = y + my[i], newz= zero + mz[i];
if (newx > 2 || newx < 0 || newy > 2 || newy < 0) continue;
memcpy(&map[rear], &map[front], sizeof(map[front]));
map[rear][zero] = map[front][newz];
map[rear][newz] = map[front][zero]; //生成新的map,准备放入队列
ans[rear] = ans[front] + 1;
fa[rear] = front; //写着玩,印图用
if (ahash(rear)==1) rear++;
}
front++;
}
}
int main()
{
int i,sum;
for (i = 0; i < 9; i++)
cin >> map[1][i];
for (i = 0; i < 9; i++)
cin >> goal[i];
sum = bfs();
cout << ans[sum]<<endl;
for (i = sum; fa[i] != 0; i = fa[i]) //写着玩
{
print(i);
cout << "\n\n";
}
system("pause");
}
下面给出一个Java版本..
package acm;
import java.util.*;
import java.io.*;
public class Acm {
static public String mapString;
// public int zeroPoint[]; // 0 and 1 is the location in map, well 3 is the location in string
public Map<Integer, Set> hashtable;
public Queue<EachString> bfstable;
public class EachString {
// the class for the string and his dfs times
String theString;
int theTimes;
public EachString(char[] tmp) {
theString = new String(tmp);
theTimes = 0;
}
public EachString() {
theTimes = 0;
}
};
public static int[] direction = {-3, +3, -1, +1};
public Acm() {
hashtable = new HashMap<Integer, Set>();
bfstable = new LinkedList<EachString>();
}
public int getZeroPoint(String mapNow) {
int zeroPoint; // the location in string
for(int i = 0; i < mapNow.length(); i++) {
if (mapNow.charAt(i) == '0' ) {
zeroPoint = i;
return zeroPoint;
}
}
// false
return zeroPoint = 0;
}
public boolean PutToHash(String theString){
// check and push
// System.out.println(theString);
int nowHash = Integer.parseInt(theString) / 100000000;
Set <String> thisSet = hashtable.get(nowHash);
if (thisSet != null) {
if (!thisSet.contains(theString)) {
thisSet.add(theString);
return true;
}
}
else {
thisSet = new TreeSet<String>();
thisSet.add(theString);
hashtable.put(nowHash, thisSet);
return true;
}
return false;
}
public void BFS() {
EachString theMapEachString = new EachString();
theMapEachString.theString = mapString;
bfstable.add(theMapEachString);
while(!bfstable.isEmpty()) {
EachString nowEachString = bfstable.poll();
// System.out.print("nowString" + nowString);
int nowZeroPoint = getZeroPoint(nowEachString.theString);
// char[][] nowMapString = new char[3][3];
// nowMapString = nowString.toCharArray();
for (int i : direction) {
int tmp = nowZeroPoint + i;
if (tmp > 8 || tmp < 0) {
continue;
}
if ((i == 1 || i == -1) && tmp / 3 != nowZeroPoint / 3) {
continue;
}
if (nowEachString.theString.equals("123456780")) {
System.out.println("Finishde! " + nowEachString.theTimes);
return;
}
char[] newChar = nowEachString.theString.toCharArray();
char trans = newChar[tmp];
newChar[tmp] = newChar[nowZeroPoint];
newChar[nowZeroPoint] = trans;
EachString theNewEachString = new EachString(newChar);
if (PutToHash(theNewEachString.theString)) {
theNewEachString.theTimes = nowEachString.theTimes + 1;
bfstable.add(theNewEachString);
}
}
}
}
public static void main(String[] args) {
Acm acm = new Acm();
Scanner scanf = new Scanner(System.in);
acm.mapString = scanf.nextLine();
acm.BFS();
}
// 1234567890
/* 0 1 2 3 x
* 0 1 2 3
* 1 4 5 6
* 2 7 8 0
* 3
* y
*
* 0 1 2 | 3 4 5 | 6 7 8
* 1 3 6 0 4 8 2 5 7
*/
}