Codevs 1225 八数码难题
2016-06-11 16:53
405 查看
1225 八数码难题
时间限制: 1 s
空间限制: 128000 KB
题目等级 : 钻石 Diamond
题目描述 Description
Yours和zero在研究A*启发式算法.拿到一道经典的A*问题,但是他们不会做,请你帮他们.
问题描述
在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字。棋盘中留有一个空格,空格用0来表示。空格周围的棋子可以移到空格中。要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765),找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变。
输入描述 Input Description
输入初试状态,一行九个数字,空格用0表示
输出描述 Output Description
只有一行,该行只有一个数字,表示从初始状态到目标状态需要的最少移动次数(测试数据中无特殊无法到达目标状态数据)
样例输入 Sample Input
283104765
样例输出 Sample Output
4
开一个结构体,结构体内开一个3*3的数组,储存每一步的棋局,方便棋局的改变,再加一个hash判重。个人认为其实不用双向bfs,一路搜过去就行了。
细节再看代码。
时间限制: 1 s
空间限制: 128000 KB
题目等级 : 钻石 Diamond
题目描述 Description
Yours和zero在研究A*启发式算法.拿到一道经典的A*问题,但是他们不会做,请你帮他们.
问题描述
在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字。棋盘中留有一个空格,空格用0来表示。空格周围的棋子可以移到空格中。要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765),找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变。
输入描述 Input Description
输入初试状态,一行九个数字,空格用0表示
输出描述 Output Description
只有一行,该行只有一个数字,表示从初始状态到目标状态需要的最少移动次数(测试数据中无特殊无法到达目标状态数据)
样例输入 Sample Input
283104765
样例输出 Sample Output
4
思路
题目要求将初始状态移动到目标状态,移动的都是0,即空出来的一个格子。开一个结构体,结构体内开一个3*3的数组,储存每一步的棋局,方便棋局的改变,再加一个hash判重。个人认为其实不用双向bfs,一路搜过去就行了。
细节再看代码。
#include<cstdio> #include<cstring> #include<string> #include<iostream> using namespace std; struct node //棋局结构体 { int num[3][3]; }abc[1000000]; int step[1000000],flag; int g[3][3]={{1,2,3},{8,0,4},{7,6,5}};//目标棋局 int x[4]={0,1,0,-1},y[4]={1,0,-1,0};//移动方向 int hash[3733800]; int head,tail; bool Hash()//hash 判重 { int s=0,k=1; for(int i=0;i<3;i++) for(int j=0;j<3;j++) { s+=abc[tail].num[i][j]*k; k*=7; } s%=373899;//极大素数,基本不会重复 if(!hash[s]) { hash[s]=1; return 1; } return 0; } int pd(int x,int y)//判断是否越界 { if (x>=0 && x<3 && y>=0 && y<3) return 1; return 0; } bool PD() //判断是否出现目标棋局 { for(int i=0;i<3;i++) for(int j=0;j<3;j++) if(abc[tail].num[i][j]!=g[i][j]) return 0; return 1; } void move(int i,int j)// 空格移动 { int xx,yy; for(int k=0;k<4;k++) { xx=i+x[k]; yy=j+y[k]; if(pd(xx,yy)) { for(int m=0;m<3;m++) for(int n=0;n<3;n++) abc[tail].num[m] =abc[head].num[m] ; swap(abc[tail].num[i][j],abc[tail].num[xx][yy]); step[tail]=step[head]+1; if(PD()) { cout<<step[tail]<<endl; flag=1; return; } if(Hash()) tail++; } } } void bfs() //bfs一下 { while(head<tail) { for(int i=0;i<3;i++) for(int j=0;j<3;j++) { if(abc[head].num[i][j]==0) move(i,j); if(flag) return; } head++; } } int main() { string s; int t=0; cin>>s; for(int i=0;i<3;i++) for(int j=0;j<3;j++) abc[0].num[i][j]=s[t]-'0',t++; tail=1; bfs(); return 0; }
相关文章推荐
- Android 不能使用内部资源
- C++中const详解
- 广度优先搜索 cdoevs 1226 倒水问题
- ScrollView 里面 嵌套ListView 导致listview无法完全显示数据的问题
- Spring AOP初步了解
- JavaWeb学习笔记之SSM框架搭建配置文件
- UIButton的ImageView与TitleLabel对齐
- 这是一个JavaScript小算法
- 图像分割评价标准 代码 (Image segmentation evaluation metrics code)
- cocos2D-X源码分析之从cocos2D-X学习OpenGL(12)----立方体贴图和天空盒
- Android的线程和线程池
- [bzoj3754][GDOI2014模拟]Tree
- 《JavaScript学习笔记》:拖拽
- ContentType明细对照表(文件类型相关的设置)
- 浅谈PHP内核与服务器
- Plus One
- C语言实现星号点号的交错打印
- Vi讲得好
- XM_NSNotification(一个能够自动移除监听对象保证通知安全的小助手)
- XML 学习笔记