八数码
来源:互联网 发布:华师大网络教育 编辑:程序博客网 时间:2024/04/29 06:27
#include<iostream>#include<cmath> //为用abs多花了15个长度(本人喜欢“缩减”(减短长度)代码)using namespace std;string qs[1000001],data[1000001],s,c,start,gz[9]={"13","240","51","046","1573","284","37","486","57"}; //qs用来放变化队列,而data用来判重。s用来在每一次交换数字的时候判重并判断是否已经是结果了。c是放队列的头。start放起始状态,gz放九个格子分别相邻的地方。int sum,list[1000001]={0},next[1000001]={0},u,tim[1000001],cnt=0,t,x,p;char tmp; //sum list next u cnt跟哈希有关,tim、t放步数,x p tmp用来交换。int hash(string h) //哈希{ sum=0; for(int i=0;i<h.size();i++)sum=sum*33+h[i]; sum=abs(sum%1000007),u=list[sum]; //你不加ABS会RE(反正我是这样) while(u){if(data[u]==h)return 0;u=next[u];} data[++cnt]=h,next[cnt]=list[sum],list[sum]=cnt; return 1;} //用链表做哈希int bfs() //广搜上场。{ int head=0,tail=1; while(head<tail) { head++,c=qs[head],t=tim[head],x=c.find("0",0); //先找到空格位置。 for(int i=0;i<gz[x].size();i++) //进行交换 { s=c,p=gz[x][i]-48; //开始找交换位置 tmp=s[x],s[x]=s[p],s[p]=tmp; //开始交换 if(s=="123804765"){cout<<t+1;return 0;} //交换完毕后如果结束,则退出 if(hash(s))tail++,qs[tail]=s,tim[tail]=t+1;} //如果没有重复就入队 }}int main(){ cin>>start; if(start=="123804765"){cout<<"0";return 0;} //如果一开始就达到目标就直接结束。 qs[1]=start,tim[1]=0,bfs(); //否则开始宽搜}
A*:个人认为A*比双向宽搜好写的多,代码长度也是很短,估价函数非常容易想到,即当前所有1-8(不包括0)数字位置与目标位置的距离之和,在这里可能会出现一个疑问:为什么是不包括0的?我刚开始也是打上0,的仔细研究之后可以发现答案都偏大2左右(其实把Ans-2也可以A了数据太水)后来发现:只要1-8的数字都完美地和目标位置匹配了,那0这个可以自由移动的数字也自然在目标位置上了,故可以估价的时候不统计(在这里可以不把0看成一个需要转移到目标位置上的数字,而是不存在的缺口,可能会有助于理解)接下来可以迭代枚举答案,每次记录0坐标即可,若 当前估价值+当前步数>答案 则剪枝(因为估价值是一个完成匹配的最低限)。
#include<cstdio>#include<cstring>#include<cstdlib>#include<algorithm>using namespace std;struct A{int x,y;};int a[3][3],flag,stx,sty,Ans;int p1[4]={1,-1,0,0};int p2[4]={0,0,1,-1};int gx[9]={1,0,0,0,1,2,2,2,1};int gy[9]={1,0,1,2,2,2,1,0,0};int Guess(){ A z[9]={0};int sum=0; for(int i=0;i<=2;i++) for(int j=0;j<=2;j++) z[a[i][j]].x=i,z[a[i][j]].y=j; for(int i=1;i<9;i++) sum+=(abs(z[i].x-gx[i])+abs(z[i].y-gy[i])); return sum;}void Dfs(int now,int goal,int x,int y){ if(now>goal)return; if(flag)return;int v=Guess(); if(v==0){flag=1;return;} if(now+v>goal)return; for(int k=0;k<4;k++){ int nx=x+p1[k];int ny=y+p2[k]; if(nx<0||nx>2||ny<0||ny>2)continue; swap(a[x][y],a[nx][ny]); Dfs(now+1,goal,nx,ny); swap(a[x][y],a[nx][ny]); }}int main(){ char ch[10];scanf("%s",ch); int k=0; for(int i=0;i<3;i++) for(int j=0;j<3;j++){ a[i][j]=ch[k]-'0',k++; if(a[i][j]==0)stx=i,sty=j; }Ans=-1; while(!flag) Ans++,Dfs(0,Ans,stx,sty); printf("%d\n",Ans); return 0;}
)
2 0
- 八数码
- 八数码
- 八数码
- 八数码
- 八数码
- 八数码
- 八数码
- 八数码
- 八数码
- 八数码
- 八数码
- 八数码
- 八数码
- 八数码
- 八数码
- 八数码
- 八数码
- 八数码
- 初始化editText,隐藏键盘
- Java注解概述
- 安卓6.0权限适配 ----RxPermissions
- java学习小结
- JAVA基础知识点梳理一:常量和变量
- 八数码
- wav音频文件格式解析
- 【Mysql之自我练习<二>】select查询(注:私用的,为了不遗失)
- Oracle DBMS占用大量内存的解决方法
- UVA 1589 Xiangqi 直接模拟 提交了近50次要跪。。
- 模拟考试9.3-笨笨连线游戏(route.cpp)
- LeanCould 初体验
- 本人的第一篇博客
- Ehcache 常用配置