八数码问题
来源:互联网 发布:2017暑运大数据报告 编辑:程序博客网 时间:2024/05/15 02:40
题意
给出一个九宫格(3*3),上面有1~8共八个数字块按某个顺序排列,而有一个空格,让你通过移动使它排列成12345678空.
普通版V1.0
Aizu - ALDS1_13_B 8 Puzzle
经典版的,不过只需要输出移动次数因此可能有什么高级解法,不过我还是按书的模板打的可输出路径版.
#include<bits/stdc++.h>using namespace std;const int dx[4]={0,0,-1,1},dy[4]={-1,1,0,0};const char rd[4]={'u','d','l','r'};struct gg{ int mp[9]; int space; string path; bool operator<(const gg &tmp)const { for(int i=0;i<=8;i++) { if(mp[i]!=tmp.mp[i])return mp[i]>tmp.mp[i]; } return false; }};bool ifok(gg a){ for(int i=0;i<8;i++) if(a.mp[i]!=i+1)return false; return true; }gg bfs(gg bg){ queue<gg> q;gg now,tmp;int x,y; map<gg,bool>vis; vis[bg]=1; q.push(bg); while(!q.empty()) { now=q.front();q.pop(); if(ifok(now))return now; x=now.space%3;y=now.space/3; for(int i=0;i<=3;i++) { tmp=now; if(x+dx[i]<0||x+dx[i]>2||y+dy[i]<0||y+dy[i]>2)continue; tmp.space=x+dx[i]+(y+dy[i])*3; swap(tmp.mp[x+y*3],tmp.mp[x+dx[i]+(y+dy[i])*3]); tmp.path+=rd[i]; if(vis[tmp])continue; vis[tmp]=1;q.push(tmp); } } }int main(){ gg bg,ans; for(int i=0;i<=8;i++) { scanf("%d",&bg.mp[i]); if(bg.mp[i]==0)bg.space=i; } bg.path=""; ans=bfs(bg); cout<<ans.path.length()<<endl;//话说aoj老是卡换行,没有就pe...}
升级版V2.0
HDU - 1043 八数码
数据不只一组,因此每次搜会tle加mle…所以首先预处理,从结尾情况往回推出每一种情况的最短路径,然后O(1)查询就好了,注意因为是反推的,所以答案反着输出就行了.
#pragma GCC optimize(2)#include<bits/stdc++.h>using namespace std;const short dx[4]={0,0,-1,1},dy[4]={-1,1,0,0};const char rd[4]={'d','u','r','l'};struct gg{ short mp[9]; short space; string path; bool operator<(const gg &tmp)const { for(short i=0;i<=8;i++) { if(mp[i]!=tmp.mp[i])return mp[i]>tmp.mp[i]; } return false; }};map<gg,bool>vis;void bfs(gg bg){ queue<gg> q; gg now,tmp;short x,y; vis[bg]=1; q.push(bg); while(!q.empty()) { now=q.front();q.pop(); x=now.space%3;y=now.space/3; for(short i=0;i<=3;i++) { tmp=now; if(x+dx[i]<0||x+dx[i]>2||y+dy[i]<0||y+dy[i]>2)continue; tmp.space=x+dx[i]+(y+dy[i])*3; swap(tmp.mp[x+y*3],tmp.mp[x+dx[i]+(y+dy[i])*3]); tmp.path+=rd[i]; if(vis[tmp])continue; vis[tmp]=1;q.push(tmp); } } }int main(){ gg bg,ans;char c;string s; for(int i=0;i<8;i++) bg.mp[i]=i+1; bg.mp[8]=0;bg.space=8;bg.path="";bfs(bg); while(~scanf(" %c",&c)) {if(c=='x')bg.space=0,bg.mp[0]=0; else bg.mp[0]=c-'0'; for(short i=1;i<=8;i++) {scanf(" %c",&c); if(c=='x')bg.space=i,bg.mp[i]=0; else bg.mp[i]=c-'0';} bg.path=""; map<gg,bool>::iterator pos=vis.find(bg); if(pos!=vis.end()) { s=pos->first.path; reverse(s.begin(),s.end()); } else s="unsolvable"; cout<<s<<endl; }}
终极版VMax.0
POJ - 1077 Eight
题面与之前相同,只有一组测试输出路径,不过貌似数据特别特别强大,之前1.0版和2.0版都过不了(tle)…没办法只能写了1.0的astar版(话说改改估计连15数码都可以水过了哈)
#include<iostream>#include<cstdio>#include<queue>#include<algorithm>#include<map>using namespace std;const int dx[4]={0,0,-1,1},dy[4]={-1,1,0,0};const char rd[4]={'u','d','l','r'};int mdd[9][9];struct gg{ int mp[9],md; int space; string path; bool operator<(const gg &tmp)const { for(int i=0;i<=8;i++) { if(mp[i]!=tmp.mp[i])return mp[i]>tmp.mp[i]; } return false; }};struct state{ gg g; int e; friend bool operator<(state a,state b) { return a.e>b.e; }};int getmd(gg g){ int ret=0; for(int i=0;i<=8;i++) if(g.mp[i]!=0)ret+=mdd[i][g.mp[i]-1]; return ret;}gg bfs(gg bg){ priority_queue<state> q;gg now,tmp;int x,y;state tp,ne; map<gg,bool>vis; state init; init.g=bg;init.e=getmd(bg); q.push(init); while(!q.empty()) { tp=q.top();q.pop();now=tp.g; if(now.md==0)return now; vis[now]=1; x=now.space%3;y=now.space/3; for(int i=0;i<=3;i++) { if(x+dx[i]<0||x+dx[i]>2||y+dy[i]<0||y+dy[i]>2)continue; tmp=now;tmp.md-=mdd[x+dx[i]+(y+dy[i])*3][tmp.mp[x+dx[i]+(y+dy[i])*3]-1]; tmp.md+=mdd[now.space][tmp.mp[x+dx[i]+(y+dy[i])*3]-1]; tmp.space=x+dx[i]+(y+dy[i])*3; swap(tmp.mp[x+y*3],tmp.mp[x+dx[i]+(y+dy[i])*3]); tmp.path+=rd[i]; if(vis[tmp])continue; ne.g=tmp;ne.e=tmp.path.length()+tmp.md;q.push(ne); } } printf("unsolvable"); }int main(){ //freopen("in.txt","r",stdin); for(int i=0;i<=8;i++) for(int j=0;j<=8;j++) mdd[i][j]=abs(i/3-j/3)+abs(i%3-j%3); gg bg,ans;char c; for(int i=0;i<=8;i++) { scanf(" %c",&c); if(c=='x')bg.space=i,bg.mp[i]=0; else bg.mp[i]=c-'0'; } bg.path="";bg.md=getmd(bg); ans=bfs(bg); cout<<ans.path;}
小总结:astar是bfs加强版,每次选取操作的元素是按一个函数f来搞的,而f是由一个当前操作数和一个估计还要操作数组成(估价函数h),这就使如果估价函数选的好可以让程序跑得飞起来,例如此处选的估价函数就是每个数到它应在位置的曼哈顿距离之和.
阅读全文
0 0
- 八数码问题
- [人工智能]八数码问题
- 八数码问题.....
- 八数码问题
- 八数码问题分析
- 八数码问题
- 人工智能-八数码问题
- 八数码问题
- 八数码问题,Puzzle
- 八数码问题
- 八数码问题
- 八数码问题
- 八数码问题源代码
- 八数码问题
- 八数码问题
- 八数码问题
- 八数码问题
- 八数码问题
- eclipse创建maven web项目更改servlet版本小技巧
- 经验总结-完整介绍Android Studio中Git的使用之git的基本准备及提交代码到本地(一)-2
- Spring Boot学习总结(9)——SpringBoot集成Ehcache3.x
- ELK 完整部署和使用
- POJ 2318 TOYS <计算几何>
- 八数码问题
- Maven3 快速入门
- 微信小程序入门-事件冒泡、模板、视图渲染
- 2017CCPC秦皇岛 E:String of CCPC
- Qt下MSVC/Mingw平台dump/crash log报告调试方法差异
- hdu 6225 Little Boxes
- String of CCPC(CCPC秦皇岛)
- java 水仙花
- 关于我的博客