您的位置:首页 > 其它

codevs1225 八数码难题

2016-07-16 20:11 274 查看
题目描述 Description

Yours和zero在研究A*启发式算法.拿到一道经典的A*问题,但是他们不会做,请你帮他们.
问题描述


3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字。棋盘中留有一个空格,空格用0来表示。空格周围的棋子可以移到空格中。要求解的问题是:
给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765),找到一种最少步骤的移动方法,实现从初始布局到目标布局的
转变。



输入描述
Input Description


输入初试状态,一行九个数字,空格用0表示



输出描述
Output Description


只有一行,该行只有一个数字,表示从初始状态到目标状态需要的最少移动次数(测试数据中无特殊无法到达目标状态数据)



样例输入
Sample Input


283104765



样例输出
Sample Output


4

正解:BFS+hash

解题报告:

  向总让我写标程,然后我就愉快地开始写这道最初学搜索时的水题,然而我第一遍wa了,mdzz

  hash判重,BFS搜索

#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long long LL;
const int MOD = 1000007;//hash的模
char ch[12];
int now;
int a[100001][10];//记录状态
int times[100001];//计算移动次数
int final[10]={1,2,3,8,0,4,7,6,5};//目标局面
int cnt,hash[1000008],next[100001],to[100001];//hash表

void insert(int x){//插入哈希表
int num=0;
for(int i=0;i<9;i++) num=num*9+a[x][i];
int ha=num%MOD;
next[++cnt]=hash[ha]; hash[ha]=cnt; to[cnt]=num;
}

bool check(int x){//哈希判重,挂链
int num=0;
for(int i=0;i<9;i++) num=num*9+a[x][i];
int ha=num%MOD;
for(int i=hash[ha];i;i=next[i])
if(to[i]==num) return false;
return true;
}

int main()
{
for(int i=0;i<9;i++) ch[i]=getchar();
for(int i=0;i<9;i++) a[1][i]=ch[i]-'0';
int head=0,tail=1; insert(1);
while(head<tail) {
head++;
for(int i=0;i<9;i++) if(a[head][i]==0) { now=i; break; }//找到当前0的位置
for(int k=-3;k<=3;k+=2) {//枚举移动的每一种可能
int to=now+k;
if(to<0 || to>=9) continue;//越界
if(now%3==2 && k==1) continue;//在右边界上不能再向右移动一格
if(now%3==0 && k==-1) continue;//在左边界不能再向左移动一格
tail++;  for(int i=0;i<9;i++) a[tail][i]=a[head][i];//把交换前的情况复制到新数组
swap(a[tail][now],a[tail][to]);//交换位置
if(check(tail)) {//得到一组可行解
times[tail]=times[head]+1;
bool ok=true;
for(int i=0;i<9;i++) if(a[tail][i]!=final[i]) { ok=false; break; }
if(ok) { printf("%d",times[tail]); return 0; }
insert(tail);
}
else tail--;//此状态已经重复,可以省略
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: