c++ 启发式搜索解决八数码问题
本文对八数码问题 启发式搜索 (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++ 启发式搜索解决八数码问题的更多相关文章
- A*算法解决八数码问题 Java语言实现
0X00 定义 首先要明确一下什么是A*算法和八数码问题? A*(A-Star)算法是一种静态路网中求解最短路径最有效的直接搜索方法也是一种启发性的算法,也是解决许多搜索问题的有效算法.算法中的距离估 ...
- 【算法】BFS+哈希解决八数码问题
15拼图已经有超过100年; 即使你不叫这个名字知道的话,你已经看到了.它被构造成具有15滑动砖,每一个从1到15上,并且所有包装成4乘4帧与一个瓦块丢失.让我们把丢失的瓷砖“X”; 拼图的目的是安排 ...
- 关于八数码问题中的状态判重的三种解决方法(编码、hash、<set>)
八数码问题搜索有非常多高效方法:如A*算法.双向广搜等 但在搜索过程中都会遇到同一个问题.那就是判重操作(假设反复就剪枝),怎样高效的判重是8数码问题中效率的关键 以下关于几种判重方法进行比較:编码. ...
- HDU 1043 Eight 八数码问题 A*算法(经典问题)
HDU 1043 Eight 八数码问题(经典问题) 题意 经典问题,就不再进行解释了. 这里主要是给你一个状态,然后要你求其到达\(1,2,3,4,5,6,7,8,x\)的转移路径. 解题思路 这里 ...
- A*算法 -- 八数码问题和传教士过河问题的代码实现
前段时间人工智能的课介绍到A*算法,于是便去了解了一下,然后试着用这个算法去解决经典的八数码问题,一开始写用了挺久时间的,后来试着把算法的框架抽离出来,编写成一个通用的算法模板,这样子如果以后需要用到 ...
- ACM/ICPC 之 BFS-广搜进阶-八数码(经典)(POJ1077+HDU1043)
八数码问题也称为九宫问题.(本想查查历史,结果发现居然没有词条= =,所谓的历史也就不了了之了) 在3×3的棋盘,摆有八个棋子,每个棋子上标有1至8的某一数字,不同棋子上标的数字不相同.棋盘上还有一个 ...
- 双向广搜+hash+康托展开 codevs 1225 八数码难题
codevs 1225 八数码难题 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description Yours和zero在研究A*启 ...
- Codevs 1225 八数码难题
1225 八数码难题 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description Yours和zero在研究A*启发式算法.拿到一道经典的 ...
- A*八数码
帮同学写的八数码,启发式搜索 创建两个表open,close,分别用的stl中的优先队列priority_queue和map,好久没写过代码了,bug调了半天 #include <iostrea ...
随机推荐
- 保姆级教程!手把手教你使用Longhorn管理云原生分布式SQL数据库!
作者简介 Jimmy Guerrero,在开发者关系团队和开源社区拥有20多年的经验.他目前领导YugabyteDB的社区和市场团队. 本文来自Rancher Labs Longhorn是Kubern ...
- Journal of Proteome Research | Improving Silkworm Genome Annotation Using a Proteogenomics Approach (分享人:张霞)
题目:Improving Silkworm Genome Annotation Using a Proteogenomics Approach 期刊:Journal of Proteome Resea ...
- 使用tomcat运行时提示some characters cannot be mapped using iso-8859-1 character encoding异常
今天第一次使用java进行jsp项目搭建,也是第一次使用tomcat.tomcat是运行java web的一个小型服务器,属于Apache的一个开源免费的服务. 在运行web 的时候,我们就要先配置好 ...
- pandas 的常用方法
pandas的常用方法: 1.数据输入 2.数据查看 3.数据清洗 4.数据处理 5.数据提取 6.数据筛选 7.数据汇总 8.数据统计 9.数据输出 详情见: https://blog.csdn.n ...
- VirtualBox 安装 Centos8 使用 Xshell 连接
1.下载CentOS CentOS下载地址:https://wiki.centos.org/Download 这里选择本地安装包,网络安装包在安装时需要在线下载资源比较慢 2.安装VirtualBox ...
- 动态规划-划分数组的最大和 Split Array Largest Sum
2019-10-14 22:13:18 问题描述: 问题求解: 解法一:动态规划 这种数组划分的题目基本都可以使用dp来解决,核心的思路就是先维护低的划分,再在中间找分割点加入新的划分. public ...
- 拒绝了对对象 '***' (数据库 'BestSoftDB_P',架构 'sale')的 EXECUTE 权限。
问题描述: 给普通用户授予读写权限,之后研发反映查询语句报错: nested exception is com.microsoft.sqlserver.jdbc.SQLServerException: ...
- 高数解题神器:拍照上传就出答案,这个中国学霸做的AI厉害了 | Demo
一位叫Roger的中国学霸小哥的拍照做题程序mathAI一下子火了,这个AI,堪称数学解题神器. 输入一张包含手写数学题的图片,AI就能识别出输入的数学公式,然后给出计算结果. 不仅加减乘除基本运算, ...
- 面试刷题30:SpringBean的生命周期?
spring是Java软件开发的事实标准. 我是李福春,我在准备面试,今天的问题是:springBean的生命周期是怎样的? 答:spring最基础的能力是IOC(依赖注入),AOP(面向切面编程), ...
- VS2015 远程调试:Remote Debugger
一.关于Remote Debugger 使用VS远程调试器Remote Debugger,我们可以调试部署在不同机器上的应用程序,如桌面应用程序和Asp.Net应用程序. 二.Remote Debug ...