【宽搜】【A星】八数码难题 WikiOI 1225 Astar
2013-05-10 13:10
225 查看
WikiOI 1225 八数码难题
题目描述Description
Yours和zero在研究A*启发式算法.拿到一道经典的A*问题,但是他们不会做,请你帮他们.问题描述
在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字。棋盘中留有一个空格,空格用0来表示。空格周围的棋子可以移到空格中。要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765),找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变。
输入描述Input Description
输入初试状态,一行九个数字,空格用0表示输出描述Output Description
只有一行,该行只有一个数字,表示从初始状态到目标状态需要的最少移动次数(测试数据中无特殊无法到达目标状态数据)样例输入Sample Input
283104765样例输出Sample Output
4这一题WikiOI上数据比较弱,普通宽搜+常数巨大的stlmap 都可以很快过
突然想写写Astar,就从这一题开始了,一开始不知道估价函数怎么写,看了受哥的博客才知道是可以乱写的(我乱说的。。。)
意思就是写法很多,而这一题受哥的 h = 当前状态与目标状态不同的格子数
然后我就这样写了,交WikiOI,测下来比普通宽搜快一点点(9ms)
想到数据比较小,就自己随即生成了数据,然后一测
A*可能是我的估价函数写球了,导致我自己做数据有些情况跑出来比普通宽搜还慢(数据是从受哥程序跑出来的)
普通bfs代码
/*http://blog.csdn.net/jiangzh7 By Jiangzh*/ #include<cstdio> #include<cstdlib> #include<iostream> #include<string> #include<queue> #include<map> using namespace std; const int dx[]={1,-1,0,0}; const int dy[]={0,0,1,-1}; const string tar="123804765"; struct ND{string sta;int x0,y0;int step;}; queue<ND> q; map<string,int> h; bool expand(ND &now,ND &node,int k) { node=now; node.step++; int x1=node.x0+dx[k]; int y1=node.y0+dy[k]; if(x1<0||x1>=3||y1<0||y1>=3) return 0; int pos1=node.x0*3+node.y0; int pos2=x1*3+y1; swap(node.sta[pos1],node.sta[pos2]); node.x0=x1; node.y0=y1; return 1; } void bfs() { while(!q.empty()) { ND now=q.front();q.pop(); //cout<<now.sta<<' '<<now.x0<<' '<<now.y0<<endl; for(int k=0;k<4;k++) { ND tmp; if(!expand(now,tmp,k)) continue; if(tmp.sta==tar) { printf("%d\n",tmp.step); exit(0); } if(!h[tmp.sta]) { h[tmp.sta]=1; q.push(tmp); } } } } int main() { freopen("1225.in","r",stdin); freopen("1225.out","w",stdout); ND st; cin>>st.sta; st.step=0; for(int i=0;i<st.sta.length();i++) if(st.sta[i]=='0') st.x0=i/3,st.y0=i%3; q.push(st); bfs(); printf("-1\n"); return 0; }
Astar代码
/*http://blog.csdn.net/jiangzh7 By Jiangzh*/ #include<cstdio> #include<iostream> #include<string> #include<queue> #include<map> using namespace std; const int dx[]={1,-1,0,0}; const int dy[]={0,0,1,-1}; const string tar="123804765"; struct ND{ string sta;int x0,y0;int f,g,h; bool operator < (const ND &a) const { return f>a.f; } }; map<string,int> h; priority_queue<ND> q; int getf(ND &tmp) { int res=0; for(int i=0;i<9;i++) if(tar[i]!=tmp.sta[i]) res++; tmp.h=res; return tmp.f=tmp.g+tmp.h; } bool expand(ND &now,ND &tmp,int k) { tmp=now; tmp.g++; int x1=now.x0+dx[k]; int y1=now.y0+dy[k]; if(x1<0||x1>=3||y1<0||y1>=3) return 0; tmp.x0=x1; tmp.y0=y1; int pos1=now.x0*3+now.y0; int pos2=tmp.x0*3+tmp.y0; swap(tmp.sta[pos1],tmp.sta[pos2]); getf(tmp); return 1; } int Astar() { while(!q.empty()) { ND now=q.top(); q.pop(); //cout<<now.sta<<' ';printf("%d %d %d\n",now.g,now.h,now.f); for(int k=0;k<4;k++) { ND tmp; if(!expand(now,tmp,k)) continue; if(tmp.sta==tar) return tmp.g; if(!h[tmp.sta]) { h[tmp.sta]=1; q.push(tmp); } } } return -1; } int main() { freopen("1225.in","r",stdin); freopen("1225.out","w",stdout); ND st; cin>>st.sta; for(int i=0;i<st.sta.length();i++) if(st.sta[i]=='0') st.x0=i/3,st.y0=i%3; st.g=0; getf(st); q.push(st); printf("%d\n",Astar()); return 0; }
相关文章推荐
- wikioi-天梯-提高一等-启发式搜索-1225:八数码难题
- wikioi 1225 八数码难题 IDA*
- 【宽搜】wikioi 1225 八数码难题
- 八数码难题 双向搜索(codevs 1225)
- codevs 1225 八数码难题
- CODE[VS] 1225 八数码难题
- 【codevs 1225】八数码难题
- 1225 八数码难题
- wikioi 1225八数码难题
- 双向广搜+hash+康托展开 codevs 1225 八数码难题
- 1225 八数码难题
- 【CodeVS1225】八数码难题
- WiKi 1225 八数码难题
- codevs 1225 八数码难题 搜索+Hash 解题报告
- 【Codevs1225】 八数码难题 BFS (1/1000)
- Codevs1225 八数码难题
- Codevs 1225 八数码难题
- codevs1225 八数码难题
- Wiki OI 1225 八数码难题
- 【codevs1225】八数码难题,如何精确地搜索