您的位置:首页 > 其它

【宽搜】【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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: