A-star算法求助

ed0707 2011-04-17 08:03:26
就是eight 数 码问题 在3×3 的棋盘,8个数 ,不同棋子上标的数字不相同。0表示空格
要求 给出一个初始状态和目标状态

找出一种从初始棋盘布局转变成目标状态的最少移动棋子步数
样例输入
1 2 3
4 5 6
7 8 0
1 2 3
7 4 5
8 0 6
样例输出
5

要求用a星算法
...全文
160 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
fight_flight 2011-04-20
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 ed0707 的回复:]
7楼的,谢谢啊,代码运行正确的 请问能不能稍微写点注释或者简单的思路,我再加分给你
[/Quote]
已经加上了注释,要加分奥

#include<iostream>
#include<vector>
using namespace std;
const int M=9;
const int N=3;
const int MAX=1000000;
typedef int State[M];//State类型用来存这9个数
State s[MAX],goal;
int dist[MAX];//这个用来存最短的移动距离
int fa[MAX];

const int K=4;
//左,上,右,下
int movex[K]={-1,0,1,0};//这个代表横轴上的移动距离
int movey[K]={0,-1,0,1};

const int MAXHASHSIZE=1000003;
int head[MAXHASHSIZE],next[MAXHASHSIZE];//这个是用来hash的数组

void init(){//初始化
dist[0]=0;
fa[0]=-1;
memset(head,0,sizeof(head));
}

int hash(const State& s){//求hash值
int v=0;
for(int i=0;i<M;++i)
v=v*10+s[i];
return v%MAXHASHSIZE;//取模
}

bool try_to_insert(int k){//试探可否将其加入,如果在hash表中存在返回false,否则返回true
int h=hash(s[k]);
int u=head[h];
while(u){
if(memcmp(s[k],s[u],sizeof(State))==0)return false;
u=next[u];
}
next[k]=head[h];
head[h]=k;
return true;
}

int bfs(){//广度优先搜索,运用了队列这一数据结构
int front=0,rear=1;//front表示出对端,rear表示入队端
int current_fa=0;
while(front<rear){
State &t=s[front];
if(memcmp(t,goal,sizeof(State))==0)return front;//找到目标位置返回
int i;
for(int z=0;z<M;++z)
if(t[z]==0)break;
int x=z/N,y=z%N;
int newx,newy,newz;
for(i=0;i<K;++i){//根据左,上,右,下四个方向分别试探
newx=x+movex[i];
newy=y+movey[i];
newz=newx*N+newy;
if(newx>=0&&newx<N&&newy>=0&&newy<N){//如果可以这样移动进入if语句
State &c=s[rear];
memcpy(c,t,sizeof(State));
c[newz]=t[z];
c[z]=t[newz];
dist[rear]=dist[front]+1;//更新新加入的距离
fa[rear]=front;//设置父节点,以便输出整条路径
if(try_to_insert(rear))++rear;//如果可以加入,rear加1
}
}
++front;
}
}

int main(){
{
for(int i=0;i<M;++i)//输入源9数
cin>>s[0][i];
}
{
for(int i=0;i<M;++i)//输入目标9数
cin>>goal[i];
}
init();//初始化
int ans=bfs();//获得目标位置
cout<<"steps :"<<dist[ans]<<endl;//输出最短移动距离
int f=ans;
vector<int> pos;//下面是输出整条移动方案
do{
pos.push_back(f);
f=fa[f];
}while(f!=-1);
for(int i=pos.size()-1;i>=0;--i){
State &t=s[pos[i]];
for(int j=0;j<M;++j){
cout<<t[j]<<" ";
if(j%N==2)cout<<endl;
}
cout<<endl;
}
return 0;
}
ed0707 2011-04-20
  • 打赏
  • 举报
回复
7楼的,谢谢啊,代码运行正确的 请问能不能稍微写点注释或者简单的思路,我再加分给你
superhackerzhang 2011-04-19
  • 打赏
  • 举报
回复
可以看我的BLOG
fight_flight 2011-04-19
  • 打赏
  • 举报
回复
代码可以的话多加点分吧,费老半天才搞定,包括输出了所有的步骤。

#include<iostream>
#include<vector>
using namespace std;
const int M=9;
const int N=3;
const int MAX=1000000;
typedef int State[M];
State s[MAX],goal;
int dist[MAX];
int fa[MAX];

const int K=4;
int movex[K]={-1,0,1,0};
int movey[K]={0,-1,0,1};

const int MAXHASHSIZE=1000003;
int head[MAXHASHSIZE],next[MAXHASHSIZE];

void init(){
dist[0]=0;
fa[0]=-1;
memset(head,0,sizeof(head));
}

int hash(const State& s){
int v=0;
for(int i=0;i<M;++i)
v=v*10+s[i];
return v%MAXHASHSIZE;
}

bool try_to_insert(int k){
int h=hash(s[k]);
int u=head[h];
while(u){
if(memcmp(s[k],s[u],sizeof(State))==0)return false;
u=next[u];
}
next[k]=head[h];
head[h]=k;
return true;
}

int bfs(){
int front=0,rear=1;
int current_fa=0;
while(front<rear){
State &t=s[front];
if(memcmp(t,goal,sizeof(State))==0)return front;
int i;
for(int z=0;z<M;++z)
if(t[z]==0)break;
int x=z/N,y=z%N;
int newx,newy,newz;
for(i=0;i<K;++i){
newx=x+movex[i];
newy=y+movey[i];
newz=newx*N+newy;
if(newx>=0&&newx<N&&newy>=0&&newy<N){
State &c=s[rear];
memcpy(c,t,sizeof(State));
c[newz]=t[z];
c[z]=t[newz];
dist[rear]=dist[front]+1;
fa[rear]=front;
if(try_to_insert(rear))++rear;
}
}
++front;
}
}

int main(){
{
for(int i=0;i<M;++i)
cin>>s[0][i];
}
{
for(int i=0;i<M;++i)
cin>>goal[i];
}
init();
int ans=bfs();
cout<<"steps :"<<dist[ans]<<endl;
int f=ans;
vector<int> pos;
do{
pos.push_back(f);
f=fa[f];
}while(f!=-1);
for(int i=pos.size()-1;i>=0;--i){
State &t=s[pos[i]];
for(int j=0;j<M;++j){
cout<<t[j]<<" ";
if(j%N==2)cout<<endl;
}
cout<<endl;
}
return 0;
}
ed0707 2011-04-19
  • 打赏
  • 举报
回复
poj1077的要求不一样啊,我这个是任意的初始状态和目标,输入也必须是矩阵式的
KeyCw88 2011-04-18
  • 打赏
  • 举报
回复
http://poj.org/problem?id=1077
然后百度“poj1077”吧。。一堆源码~
ed0707 2011-04-17
  • 打赏
  • 举报
回复
能给源代码吗。。网上找了好多都是不对的。
qq120848369 2011-04-17
  • 打赏
  • 举报
回复
简单说,就是一个状态搜索,优先队列里装的都是一个一个的棋盘状态。

算法目的是为了求目标状态最少的步数,所以每次取一个当前到目标棋盘状态估算步数最少的棋盘状态,用来更新

已有的棋盘状态或者增加棋盘状态,每次都取一个估算总步数最小的,所以当某次取出来的棋盘状态是目标状态,

那么算法就成功了。
e474420502 2011-04-17
  • 打赏
  • 举报
回复
做过 但是忘记了,一个开放队列,一个封闭队列。 大概就这样,加个 估价函数 障碍物 价值最大 一般节点为1
距离那样算就可以了,具体网上一队源码,上面的给我点启发,以后试下
qq120848369 2011-04-17
  • 打赏
  • 举报
回复
一个估算值作为优先级,一个开放队列,一个封闭队列。

每次从开放队列取一个估算值最优的并放入封闭队列,如果估算值已经为0,则算法结束,否则做4个方向的扩展,如果某方向移动后棋盘状态已经在开放队列内(做哈希表记录,是棋盘状态作key的一个哈希,棋盘状态可以抽二进制压缩存储),则更新其前驱与估算值(同样更新在哈希表里),如果在封闭队列内,则不操作。

A*算法有一篇非常专业的迷宫搜索范例,已经翻译成中文了,搜一下就会找到,我就是靠他学会的。
代码下载:完整代码,可直接运行 ;运行版本:2014a或2019b;若运行有问题,可私信博主; 博主优势:精通Matlab各领域,且各项目代码较全,可供指导交流。 座右铭:行百里者,半于九十。 1 第一步:海神之光博主主页https://blog.csdn.net/TIQCmatlab?type=blog 2 第二步:搜索相关内容,回车或者点击;然后就出现您需要的文章: 3 Matlab软件下载 与善其事,必先利其器。学习matlab,必须要先下载好matlab软件。 下载链接:Matlab R2020a版安装下载详细操作步骤【Matlab 140期】 4 Matlab基础教程 我们在学习matlab时,如果前面所学知识有部分遗忘,可以及时翻阅课本加深记忆。因此,虽然现在互联网已经非常的发达,但是有一本纸质版的图书也是非常有必要的。 5 学会使用互联网查找知识 现在的互联网非常强大,只靠一本纸质书籍是远远不够的。我们还要学会在网上找一些matlab相关的基础知识进行学习。 6及时进行练习,以免眼高手低 matlab软件要及时的使用起来。我们在学习基础知识时,肯定会遇到很多的小的例子。即使我们对这些例子都能理解也要多使用matlab软件进行验证,看看我们敲出来代码是否也能正常运行。 7 遇到问题及时向博主求助 作为初学者,遇见不会的问题是非常正常的事情。海神之光擅长领域擅长路径规划、优化求解、神经网络预测、图像处理、语音处理等多种领域Matlab仿真,具体代码仿真 私信博主。
代码下载:完整代码,可直接运行 ;运行版本:2014a或2019b;若运行有问题,可私信博主; 博主优势:精通Matlab各领域,且各项目代码较全,可供指导交流。 座右铭:行百里者,半于九十。 1 第一步:海神之光博主主页https://blog.csdn.net/TIQCmatlab?type=blog 2 第二步:搜索相关内容,回车或者点击;然后就出现您需要的文章: 3 Matlab软件下载 与善其事,必先利其器。学习matlab,必须要先下载好matlab软件。 下载链接:Matlab R2020a版安装下载详细操作步骤【Matlab 140期】 4 Matlab基础教程 我们在学习matlab时,如果前面所学知识有部分遗忘,可以及时翻阅课本加深记忆。因此,虽然现在互联网已经非常的发达,但是有一本纸质版的图书也是非常有必要的。 5 学会使用互联网查找知识 现在的互联网非常强大,只靠一本纸质书籍是远远不够的。我们还要学会在网上找一些matlab相关的基础知识进行学习。 6及时进行练习,以免眼高手低 matlab软件要及时的使用起来。我们在学习基础知识时,肯定会遇到很多的小的例子。即使我们对这些例子都能理解也要多使用matlab软件进行验证,看看我们敲出来代码是否也能正常运行。 7 遇到问题及时向博主求助 作为初学者,遇见不会的问题是非常正常的事情。海神之光擅长领域擅长路径规划、优化求解、神经网络预测、图像处理、语音处理等多种领域Matlab仿真,具体代码仿真 私信博主。

64,681

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧