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搜索
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; }
相关文章推荐
- 排序算法之归并排序
- linux第一天学习1
- PAT--1015. Reversible Primes
- Android中的IntentFilter
- UVA 11243 Texas Trip ------ UVALIVE 3954 Phone Cell
- hibernate学习 hibernate-tutorials(四)——envers
- puts ()
- Spiral Matrix leetcode
- 【bzoj2456】 mode
- 代码执行顺序
- 开始写博客了
- scan design flow(一)
- [置顶] (巨坑)长期经验总结
- 如何在Android Studio中创建一个selector.xml文件
- 关于sqrt()函数的一个很尴尬的细节……
- mode(BZOJ 2456)
- shell编程基础笔记
- Maven Package Compilation Error
- 10017---SpringMVC--RESTful SpringMVC CRUD
- Android 隐式意图激活另外一个Actitity