题目链接:
题目描述 Description
Yours和zero在研究A*启发式算法.拿到一道经典的A*问题,但是他们不会做,请你帮他们. 问题描述
在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字。棋盘中留有一个空格,空格用0来表示。空格周围的棋子可以移到空格中。要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765),找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变。
输入描述 Input Description
输入初试状态,一行九个数字,空格用0表示
输出描述 Output Description
只有一行,该行只有一个数字,表示从初始状态到目标状态需要的最少移动次数(测试数据中无特殊无法到达目标状态数据)
样例输入 Sample Input
283104765
样例输出 Sample Output
4
思路:
bfs + hash判重,不用Astart能过
/*************************************************************************
> File Name: 八数码bfs_1.cpp
> Author: dulun
> Mail: dulun@xiyoulinux.org
> Created Time: 2016年03月19日 星期六 17时04分02秒
************************************************************************/
#include<iostream>
#include<stdio.h>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#define LL long long
using namespace std;
typedef int State[9];
const int N = 1000000;
const int HASH = 1000003;
int head[HASH];
int next[N];
int dist[N];
State st[N], goal = {1,2,3,8,0,4,7,6,5};
int hash(State& s)
{
int v=0;
for(int i = 0; i < 9; i++) v = v*10 + s[i];
return v % HASH;
}
int try_insert(int s)
{
int h = hash(st[s]);
int u = head[h];
while(u)
{
if(memcmp(st[u], st[s], sizeof(st[s])) == 0) return 0;
u = next[u];
}
next[s] = head[h];
head[h] = s;
return 1;
}
const int dx[] = {0, 0, 1, -1};
const int dy[] = {1, -1, 0, 0};
int bfs()
{
int front = 1, rear = 2;
while(front < rear)
{
State& s = st[front];
if(memcmp(goal, s, sizeof(s)) == 0) return dist[front];
int z0;
for(z0 = 0; z0 < 9; z0++) if(!s[z0]) break;
int x0 = z0/3, y0 = z0%3;
for(int i = 0; i < 4; i++)
{
int x = x0+dx[i];
int y = y0+dy[i];
int z = 3*x+y;
if(x>=0 && x<3 && y>=0 && y<3)
{
State& t = st[rear];
memcpy(&t, &s, sizeof(s));
t[z] = s[z0];
t[z0] = s[z];
dist[rear] = dist[front] + 1;
if(try_insert(rear)) rear++;
}
}
front++;
}
return 0;
}
int main()
{
char s[10];
cin>>s;
for(int i = 0; i < 9; i++) st[1][i] = s[i]-'0';
// for(int i = 0; i < 9; i++) scanf("%d", &goal[i]);
int ans = bfs();
cout<<ans<<endl;
return 0;
}