本文对八数码问题 启发式搜索 (C++)做了一点点修改

 //fn=gn+hn

 #include<iostream>
#include<queue>
#include<stack> using namespace std; #define num 9 struct node
{
int state[];//当前状态
struct node* parent;//父节点
int value;//值
int depth;//在树中的深度
friend bool operator < (node A, node B) //按照value值小的方案构造优先级队列
{
return A.value > B.value;
}
}; priority_queue<node> openTable; //open表
queue<node> closeTable; //close表
stack<node> Path; //最终路径 void init(node& s,node& g)
{//初始化
s.parent=NULL;
s.depth=;
s.value=;
g.parent=NULL;
g.depth=;
g.value=; cout<<"please input the init status"<<endl;
for(int i=;i<num;i++)
{
cin>>s.state[i];
} cout<<"please input the target status"<<endl;
for(int i=;i<num;i++)
{
cin>>g.state[i];
} } bool isreachable(node s,node g)
{//判断目标是否可达。若2个状态的逆序奇偶性相同则可达,不相同则不可达。
int count1=;
int count2=;
for(int i=;i<=num-;i++)
{
for(int j=i+;j<num;j++)
{
if(s.state[i]>s.state[j]&&s.state[i]*s.state[j]!=)
{
count1++;
}
}
} for(int i=;i<=num-;i++)
{
for(int j=i+;j<num;j++)
{
if(g.state[i]>g.state[j]&&g.state[i]*g.state[j]!=)
{
count2++;
}
}
} if(count1%!=count2%)
{
return false;
}
return true; } int value(node a,node g)
{//hn
int count=;
for(int i=;i<num;i++)
{
if(a.state[i]==)
{
continue;
}
else if(a.state[i]!=g.state[i])
{
for(int j=;j<num;j++)
{
if(a.state[i]==g.state[j])
{
count+=abs(i/-j/)+abs(i%-j%);
}
}
}
}
return count+a.depth;
} bool isequal(node a,node g)
{//当前节点是否是目标
for(int i=;i<num;i++)
{
if(a.state[i]!=g.state[i])
{
return false;
}
}
return true;
} bool createNode(node& a,node g)
{//产生新节点,加入open表
bool flag=true;
/* 计算原状态下,空格所在的行列数,从而判断空格可以往哪个方向移动 */
int blank;//定义空格下标
for(blank=;blank<num;blank++)
{
if(a.state[blank]==)
{
break;
}
}
if(blank==num)return false;
int x=blank/,y=blank%;//获取空格所在行列编号
/*找到S扩展的子节点,加入open表中*/
for(int d=;d<;d++)
{
int newx=x,newy=y;//新空白格坐标
node tempnode;//临时节点,子节点 /*移动空格*/
switch (d)
{
case ://向上
newx--;
if(newx<)continue;
break;
case ://向左
newy--;
if(newy<)continue;
break;
case ://向下
newx++;
if(newx>)continue;
break;
case ://向右
newy++;
if(newy>)continue;
break; default:
break;
} /*交换新旧空白格的内容*/
int newblank=newx*+newy;//新空格下标 if (newx >= && newx < && newy >= && newy < )
{
tempnode=a;
tempnode.state[blank]=tempnode.state[newblank];
tempnode.state[newblank]=;
if(a.parent!=NULL&&(*a.parent).state[newblank]==)
{//如果新节点和爷爷节点一样,舍弃该节点
continue;
} /*把子节点都加入open表中*/
tempnode.parent=&a;
tempnode.value=value(tempnode,g);
tempnode.depth=a.depth+;
openTable.push(tempnode);
}
}
return flag;
} bool findpath(node s,node g)
{//s->g
bool flag=true;
/*find path*/
openTable.push(s);
while(true)
{
closeTable.push(openTable.top());
openTable.pop();
if(!isequal(closeTable.back(),g))
{
flag=createNode(closeTable.back(),g);
}
else
{
break;
} }
/*make path*/
node tempnode;
tempnode=closeTable.back();
while(tempnode.parent!=NULL)
{
Path.push(tempnode);
tempnode=*(tempnode.parent);
}
Path.push(tempnode);
return flag;
} void printpath()
{//print path s -> g
cout<<"move "<<Path.size()-<<" step"<<endl;
while(Path.size()!=)
{
for(int i=;i<num;i++)
{
cout<<Path.top().state[i]<<" ";
if((i+)%==)cout<<endl;
}
Path.pop();
cout<<endl;
}
} int main()
{
node s,g;
init(s,g);
if(!isreachable(s,g))
{
cout<<"cannot reach"<<endl;
system("pause");
return ;
}
else if (!findpath(s,g))
{
cout<<"findpath error"<<endl;
system("pause");
return ;
}
else
{
printpath();
cout<<"done"<<endl;
}
system("pause");
return ;
}

c++ 启发式搜索解决八数码问题的更多相关文章

  1. A*算法解决八数码问题 Java语言实现

    0X00 定义 首先要明确一下什么是A*算法和八数码问题? A*(A-Star)算法是一种静态路网中求解最短路径最有效的直接搜索方法也是一种启发性的算法,也是解决许多搜索问题的有效算法.算法中的距离估 ...

  2. 【算法】BFS+哈希解决八数码问题

    15拼图已经有超过100年; 即使你不叫这个名字知道的话,你已经看到了.它被构造成具有15滑动砖,每一个从1到15上,并且所有包装成4乘4帧与一个瓦块丢失.让我们把丢失的瓷砖“X”; 拼图的目的是安排 ...

  3. 关于八数码问题中的状态判重的三种解决方法(编码、hash、&lt;set&gt;)

    八数码问题搜索有非常多高效方法:如A*算法.双向广搜等 但在搜索过程中都会遇到同一个问题.那就是判重操作(假设反复就剪枝),怎样高效的判重是8数码问题中效率的关键 以下关于几种判重方法进行比較:编码. ...

  4. HDU 1043 Eight 八数码问题 A*算法(经典问题)

    HDU 1043 Eight 八数码问题(经典问题) 题意 经典问题,就不再进行解释了. 这里主要是给你一个状态,然后要你求其到达\(1,2,3,4,5,6,7,8,x\)的转移路径. 解题思路 这里 ...

  5. A*算法 -- 八数码问题和传教士过河问题的代码实现

    前段时间人工智能的课介绍到A*算法,于是便去了解了一下,然后试着用这个算法去解决经典的八数码问题,一开始写用了挺久时间的,后来试着把算法的框架抽离出来,编写成一个通用的算法模板,这样子如果以后需要用到 ...

  6. ACM/ICPC 之 BFS-广搜进阶-八数码(经典)(POJ1077+HDU1043)

    八数码问题也称为九宫问题.(本想查查历史,结果发现居然没有词条= =,所谓的历史也就不了了之了) 在3×3的棋盘,摆有八个棋子,每个棋子上标有1至8的某一数字,不同棋子上标的数字不相同.棋盘上还有一个 ...

  7. 双向广搜+hash+康托展开 codevs 1225 八数码难题

    codevs 1225 八数码难题  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond   题目描述 Description Yours和zero在研究A*启 ...

  8. Codevs 1225 八数码难题

    1225 八数码难题 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description Yours和zero在研究A*启发式算法.拿到一道经典的 ...

  9. A*八数码

    帮同学写的八数码,启发式搜索 创建两个表open,close,分别用的stl中的优先队列priority_queue和map,好久没写过代码了,bug调了半天 #include <iostrea ...

随机推荐

  1. for循环与串行化、并行化Stream流性能对比

    第四章 并行化Stream流 关注公众号(CoderBuff)回复"stream"获取<Java8 Stream编码实战>PDF完整版. <Java8 Strea ...

  2. ECCV 2018 目标检测 | IoU-Net:将IoU的作用发挥到极致

    常见的目标检测算法缺少了定位效果的学习,IoU-Net提出IoU predictor.IoU-guided NMS和Optimization-based bounding box refinement ...

  3. python基本数据类型及其使用方法

    前言 ​ python中的数据类型主要为int.float.string.list.tuple.dict.set.bool.bytes.接下来int和float统称为数字类型. 1.数据类型总结 按存 ...

  4. drf-jwt的过滤,筛选,排序,分页组件

    目录 自定义drf-jwt配置 案例:实现多方式登陆签发token urls.py models.py serializers.py views.py 案例:自定义认证反爬规则的认证类 urls.py ...

  5. java基础-对集合(Collection)的总结

    集合(Collection)类型也是Java标准库中被使用最多的类型. List ArrayList LinkedList 对于自定义的对象,需要正确覆写 equals方法 参看7.3 例子 Map ...

  6. 被问到到http的时候你就这么回答!

    大家好,我是标题党,啊不,我是小雨小雨,致力于分享有趣的.实用的技术文章. 内容分为翻译和原创,如果有问题,欢迎随时评论或私信,希望和大家一起进步. 分享不易,希望能够得到大家的支持和关注. 什么是互 ...

  7. 字符串-mask-每个元音包含偶数次的最长子字符串

    2020-03-08 00:23:04 问题描述: 给你一个字符串 s ,请你返回满足以下条件的最长子字符串的长度:每个元音字母,即 'a','e','i','o','u' ,在子字符串中都恰好出现了 ...

  8. 我们是怎么实现gRPC CodeFirst-生成proto

    前言: gRPC默认是ProtoFirst的,即先写 proto文件,再生成代码,需要人工维护proto,生成的代码也不友好,所以出现了gRPC CodeFirst,下面来说说我们是怎么实现gRPC ...

  9. OpenCV-Python 轮廓属性 | 二十三

    目标 在这里,我们将学习提取一些常用的物体属性,如坚实度,等效直径,掩模图像,平均强度等.更多的功能可以在Matlab regionprops文档中找到. (注:质心.面积.周长等也属于这一类,但我们 ...

  10. Leetcode_239. 滑动窗口最大值

    单调队列模板题,扫描一遍,队尾维护单调性,队头维护不超过大小为k的区间. code class Solution { public: vector<int> maxSlidingWindo ...