人工智能导论搜索算法实验

  • 使用说明
  • 题目要求
  • 开始写代码之前的思考:
      • 建立图
    • 考虑深度优先搜索策略:
      • 给出DFS的代码:
      • 主函数
      • 运行结果如下:
    • 考虑宽度优先搜索策略
      • 实现代码
        • 输出结果:
    • 考虑迭代加深的深度优先搜索
      • 代码如下:
        • 输出结果:
    • 考虑一致代价搜索
      • 代码
        • 一致代价输出结果:
    • 考虑贪婪优先搜索
      • 贪婪优先代码
        • 贪婪优先输出结果:
    • 考虑A*优先搜索
      • 代码
        • A*输出结果:
    • 性能对比图

使用说明

建立图的代码,下面接上算法代码和主函数代码即可编译运行。

仅供借鉴思路,不建议完全复制粘贴。

给出链接:
六合一搜索算法完整代码

题目要求

一、实验目的
• 了解4种无信息搜索策略和2种有信息搜索策略的算法思想;
• 能够运用计算机语言实现搜索算法;
• 应用搜索算法解决实际问题(如罗马尼亚问题);
• 学会对算法性能的分析和比较
二、实验的硬件、软件平台
硬件:计算机
软件:操作系统:WINDOWS/Linux
应用软件:C,Java或者MATLAB
三、实验内容及步骤
使用搜索算法实现罗马尼亚问题的求解
要求分别编写:宽度优先搜索,深度优先搜索,一致代价搜索,迭代加深的深度优先搜索算法以及实现贪婪最佳优先搜索和A*搜索算法。
并使用编写的搜索算法代码求解罗马尼亚问题;

开始写代码之前的思考:

建立图

如何把罗马尼亚问题给出的信息图作为已知信息保存呢?数据结构中学过,存图一般可以有两种方式,邻接表或连接矩阵。对于这个图,有20个节点,我们可以使用较容易实现的连接矩阵(二维数组,将每个城市抽象为数组下标,两个城市之间不可到达的值记为-1,可到达则记录路线长度)。

#include<iostream>
#include <functional>
#include<stack>
#include<vector>
#include<queue>
#include<memory.h>
using namespace std;
//城市名的首字母按照字母顺序进行编号,采用宏定义编译后续代码的理解
#define A 0
#define B 1
#define C 2
#define D 3
#define E 4
#define F 5
#define G 6
#define H 7
#define I 8
#define L 9
#define M 10
#define N 11
#define O 12
#define P 13
#define R 14
#define S 15
#define T 16
#define U 17
#define V 18
#define Z 19
#define visited 1 //标记已访问
#define not_visit 0//标记未访问
string city[20]= {"A","B","C","D","E","F","G","H","I","L","M","N","O","P","R","S","T","U","V","Z"}; //城市名称首字母
int Graph[20][20];
void init() { //初始化图信息 对应城市编号 宏记号 避免出错memset(Graph, -1, sizeof(Graph));Graph[O][Z]=71,Graph[Z][O]=71;//无向图 对应处赋值Graph[O][S]=151,Graph[S][O]=151;Graph[Z][A]=75,Graph[A][Z]=75;Graph[A][S]=140,Graph[S][A]=140;Graph[A][T]=118,Graph[T][A]=118;Graph[T][L]=111,Graph[L][T]=111;Graph[L][M]=70,Graph[M][L]=70;Graph[M][D]=75,Graph[D][M]=75;Graph[D][C]=120,Graph[C][D]=120;Graph[C][R]=146,Graph[R][C]=146;Graph[S][R]=80,Graph[R][S]=80;Graph[S][F]=99,Graph[F][S]=99;Graph[F][B]=211,Graph[B][F]=211;Graph[P][C]=138,Graph[C][P]=138;Graph[R][P]=97,Graph[P][R]=97;Graph[P][B]=101,Graph[B][P]=101;Graph[B][G]=90,Graph[G][B]=90;Graph[B][U]=85,Graph[U][B]=85;Graph[U][H]=98, Graph[H][U]=98;Graph[H][E]=86,Graph[E][H]=86;Graph[U][V]=142,Graph[V][U]=142;Graph[I][V]=92,Graph[V][I]=92;Graph[I][N]=87,Graph[N][I]=87;
}

考虑深度优先搜索策略:

深度优先策略可以采用递归实现,也可以用栈,来模仿递归过程求解,这里给出深度优先递归求解的代码:由于题目只需要找到一条路径,所以在代码中有一个返回条件是控制只搜索一个解的:(由于建图的顺序是不固定的,所以深度优先找到的路径是不唯一的,若把下面代码中一行注释,则可以找出所有的路径。按照上面的图恰找到的是经历节点最少的那一条路线)

给出DFS的代码:

const int start=A,target=B;        //起始城市为Ared,终止城市为Bucharest 该题中不能修改起始点和目标节点的位置,可在此处修改起点可终点int sum_cost=0,node_num=0;     //记录代价值
int contral=0;//DFS中只输出一条路线的控制
void DFS_Romania(int now_node,stack<int> record,int *flag) {node_num++;//递归一次,拓展的节点数++;if(flag[start]==not_visit)record.push(start);flag[now_node]=visited;//节点标记已经访问//递归结束条件,当前节点为目标节点时输出路径 if(now_node==target) { int way_num=0;//路段数stack<int> road_line; //  辅助栈  逆序record中的路径,实现路径对正序输出while(!record.empty()) {road_line.push(record.top());record.pop();}cout<<"深度优先搜索已找到目标节点,节点拓展顺序如上,路径如下:"<<endl;while(!road_line.empty()) { //输出全部的路径int temp =road_line.top();road_line.pop();cout<<city[temp];if(temp!=target) { //不是目标节点时输出符号 --(cost)--》cout<<"--("<<Graph[temp][road_line.top()]<<")-->";//将线路的cost打印出来sum_cost+=Graph[temp][road_line.top()];//总价值变化+每条路线的cost  注意这里的pop 和top的应用way_num++;}}cout<<endl<<"该路径的总消耗为: "<<sum_cost<<'\t'<<"一共经过了"<<way_num<<"个路段"<<endl;cout<<"用该搜索算法找到该路径共访问的节点个数为:"<<node_num<<"个"<<endl<<endl;sum_cost=0;//清零,下一个算法好直接用contral=1; //只输出一条可以到达的路径的控制return; //结束}cout<<"当前拓展节点为:"<<city[now_node]<<endl; //未到达目标节点 寻找下一个可拓展的节点,对该节点进行递归bool isleaf=true; //递归返回条件 是叶子节点时返回  for(int i=0; i<20; i++) { //搜索当前节点相连的未访问的节点if(Graph[now_node][i]!=-1&&flag[i]!=visited) { //能到达且未访问isleaf=false; //还有能到达的点 不是叶子节点 record.push(i);DFS_Romania(i,record,flag); //递归访问下一个节点if(contral==1) return;// 控制只要找到一条路线就返回 该行注释掉会输出所有的路径//递归返回时说明 撤销已访问标记 i的存在会避免重复进某一条 flag[i]=0; record.pop();}}if(isleaf==true) return;//到达叶子节点时 返回
}

主函数

简单调用上面的算法即可,不要忘记调用图的初始化函数和标记数组初始化为未访问。

int main() {init();//初始化图函数sum_cost=0,node_num=0;stack<int> rec;int sign[20];memset(sign,not_visit,sizeof(sign)); //DFS_Romania(start,rec,sign);return 0;
}

运行结果如下:

当前拓展节点为:A
当前拓展节点为:S
当前拓展节点为:F
深度优先搜索已找到目标节点,节点拓展顺序如上,路径如下:
A--(140)-->S--(99)-->F--(211)-->B
该路径的总消耗为: 450   一共经过了3个路段
用该搜索算法找到该路径共访问的节点个数为:4个

考虑宽度优先搜索策略

图已经建立好,宽度优先的搜索过程逐层搜索,队列可以很好的实现宽度优先。但要注意记录访问节点的父节点,便于搜索到目标节点后输出路线。给出搜索算法和主函数,在注释中有详细的思路说明:

实现代码

const int start=A,target=B;        //起始城市为Ared,终止城市为Bucharest 该题中不能修改起始点和目标节点的位置,可在此处修改起点可终点
int sum_cost=0,node_num=0;        //记录代价值
int contral=0;//DFS中只输出一条路线的控制void BFS_Romania(queue<int> record,int *parent,int *flag){record.push(start);//起始节点加入队列while(!record.empty()){int temp=record.front();//拓展节点的值node_num++;//访问节点的个数;if(temp==target){//目标节点int way_num=0;//路段数stack<int> road;road.push(temp);int i=temp;while(road.top()!=start){//将父节点压入站,达到顺序输出的目的,直到栈顶元素是开始节点为止i=parent[i];road.push(i);}cout<<"宽度优先搜索找到目标节点,路径如下:"<<endl;while(!road.empty()){i=road.top();road.pop();cout<<city[i];if(i!=target){//不是目标节点时输出符号 --(cost)--》cout<<"--("<<Graph[i][road.top()]<<")-->";//将线路的cost打印出来sum_cost+=Graph[i][road.top()];//总价值变化+每条路线的costway_num++;}}cout<<endl<<"该路径的总消耗为: "<<sum_cost<<'\t'<<"一共经过了"<<way_num<<"个路段"<<endl;cout<<"用该搜索算法找到该路径共访问的节点个数为:"<<node_num<<"个"<<endl<<endl;sum_cost=0,node_num=0;//清零,下一个算法好直接用break; //输出一条路径后就结束}cout<<"当前拓展节点为:"<<city[temp]<<"   其子节点有:";record.pop();flag[temp]=visited;for(int i=0;i<20;i++){ //不是目标 搜索当前所有的子节点if(Graph[temp][i]!=-1&&flag[i]!=visited){  //能到达且未访问record.push(i);parent[i]=temp;//更新记录父节点信息flag[i]=visited;//已经加入队列 总会访问 不能再其他节点的子节点加入cout<<city[i]<<' '; }}cout<<endl; }
}
int main() {init();//初始化 sum_cost=0,node_num=0;queue<int> rec;int sign[20];// 标记数组int parent[20];//记录每个节点的父亲节点memset(parent,-1,sizeof(parent));memset(sign,not_visit,sizeof(sign));BFS_Romania(rec,parent,sign);return 0;
}
输出结果:
当前拓展节点为:A   其子节点有:S T Z
当前拓展节点为:S   其子节点有:F O R
当前拓展节点为:T   其子节点有:L
当前拓展节点为:Z   其子节点有:
当前拓展节点为:F   其子节点有:B
当前拓展节点为:O   其子节点有:
当前拓展节点为:R   其子节点有:C P
当前拓展节点为:L   其子节点有:M
宽度优先搜索找到目标节点,路径如下:
A--(140)-->S--(99)-->F--(211)-->B
该路径的总消耗为: 450   一共经过了3个路段
用该搜索算法找到该路径共访问的节点个数为:9个

考虑迭代加深的深度优先搜索

迭代加深的深度优先算法与深度优先算法大同小异,这个算法是为了避免由于树深度过高,而目标节点又在较浅的层数,从而导致深度优先算法难以找到目标节点,但这个算法有个致命的缺点,就是如何确定受限层数。受限层数如果选择不恰当,会导致重复目标节点以上层数的点重复搜索。

代码如下:

该算法分为两个函数实现,一个是深度搜索指定层数内的点。
另一个负责不断的修改限制层数,知道搜到目标节点或整个树完全遍历;

const int start=A,target=B;        //起始城市为Ared,终止城市为Bucharest 该题中不能修改起始点和目标节点的位置,可在此处修改起点可终点
int sum_cost=0,node_num=0;        //记录代价值
int contral=0;//DFS中只输出一条路线的控制int contral2=0;
/*深度受限的子函数Iterative Deepening
*/
//对深度优先稍加修改,作为迭代加深的深度优先的子函数
void ID_DFS_Romania1(int now_node,stack<int> record,int *flag,int deeps,int now_deep) {now_deep++;//记录节点深度node_num++;//递归一次,拓展的节点数++;if(flag[start]==not_visit)record.push(start);flag[now_node]=visited;//节点标记已经访问if(now_node!=visited)cout<<"当前拓展节点为:"<<city[now_node]<<endl;if(now_node==target) { //递归结束条件,当前节点为目标节点时int way_num=0;//路段数stack<int> road_line; //  辅助栈  逆序record中的路径,实现路径对正序输出while(!record.empty()) {road_line.push(record.top());record.pop();}cout<<"深度受限的深度优先搜索已找到目标节点,受限深度为 "<<deeps<<" 时,路径如下:"<<endl;while(!road_line.empty()) { //输出全部的路径int temp =road_line.top();road_line.pop();cout<<city[temp];if(temp!=target) { //不是目标节点时输出符号 --(cost)--》cout<<"--("<<Graph[temp][road_line.top()]<<")-->";//将线路的cost打印出来sum_cost+=Graph[temp][road_line.top()];//总价值变化+每条路线的cost  注意这里的pop 和top的应用way_num++;}}cout<<endl<<"该路径的总消耗为: "<<sum_cost<<'\t'<<"一共经过了"<<way_num<<"个路段"<<endl;cout<<"用该搜索算法找到该路径共访问的节点个数为:"<<node_num<<"个"<<endl<<endl;sum_cost=0,node_num=0;//清零,下一个算法好直接用contral2=1; //只输出一条可以到达的路径的控制return; //结束}//未到达目标节点 寻找下一个可拓展的节点,对该节点进行递归bool isleaf=true; //递归返回条件if(now_deep<=deeps) {// 这里是关键,深度限制由这里实现。for(int i=0; i<20; i++) { //搜索当前节点相连的未访问的节点if(Graph[now_node][i]!=-1&&flag[i]!=visited) { //能到达且未访问isleaf=false;flag[i]=visited;//已经加入队列 总会访问 不能再其他节点的子节点加入record.push(i);ID_DFS_Romania1(i,record,flag,deeps,now_deep);//递归访问下一个节点if(contral2==1) return;// 控制只要找到一条路线就返回 该行注释掉会输出所有的路径//递归返回时说明record.pop();}}}if(isleaf==true) {now_deep--;return;//到达叶子节点时 返回}
}
void ID_DFS_Romania(int now_node,stack<int> record,int *flag,int deeps,int now_deep) {for(int i=0; i<20; i++) { //最多20层 因为只有20个节点 最开始写成 while(没找到)这里如果目标不存在则会有问题ID_DFS_Romania1(now_node,record,flag,deeps,now_deep);if(contral2==0) { //找到了sum_cost=0;//cout<<"迭代加深的深度优先算法:深度限制为 "<<deeps<<"没有成功找到目标节点"<<endl<<endl;memset(flag,not_visit,20*sizeof(int));//这里一定记得初始化 否则会少一个节点deeps++;} else break;}
}
int main() {init();//初始化sum_cost=0,node_num=0;stack<int> rec;int sign[20];memset(sign,not_visit,sizeof(sign));ID_DFS_Romania(start,rec,sign,1,1);//return 0;
}
输出结果:
当前拓展节点为:A
迭代加深的深度优先算法:深度限制为 1没有成功找到目标节点当前拓展节点为:A
当前拓展节点为:S
当前拓展节点为:T
当前拓展节点为:Z
迭代加深的深度优先算法:深度限制为 2没有成功找到目标节点当前拓展节点为:A
当前拓展节点为:S
当前拓展节点为:F
当前拓展节点为:O
当前拓展节点为:R
当前拓展节点为:T
当前拓展节点为:L
当前拓展节点为:Z
迭代加深的深度优先算法:深度限制为 3没有成功找到目标节点当前拓展节点为:A
当前拓展节点为:S
当前拓展节点为:F
深度受限的深度优先搜索已找到目标节点,受限深度为 4 时,路径如下:
A--(140)-->S--(99)-->F--(211)-->B
该路径的总消耗为: 450   一共经过了3个路段
用该搜索算法找到该路径共访问的节点个数为:17个

考虑一致代价搜索

这个搜索方式以及后面的两中方式都涉及到根据某个条件对所有的节点进行排序,这里使用优先队列(priority_queue),便于实现排序:
定义结构体,包含自己的名称,一个键值(排序的根据),一个父节点信息(便于输出路线);后面的两种算法结构与这里一致,只需要改变键值的赋值。故后面不给出解释,

代码

struct nod//自定义结构体 便于使用优先队列{int name;//节点名称 int qifa_value;// f值 或 h值 或 g值  在不同的算法里对应不同的值 int father;//父节点 friend bool operator < (nod a,nod b)//排序的关键值 {return a.qifa_value>b.qifa_value;}
};
nod node[20]; //下面三种式搜索都要用到排序 使用优先队列实现排序
priority_queue<nod>road;//优先队列
stack<nod> way;void UCS_Romania(int *flag){memset(node,-1,20*sizeof(nod));//node[start]={name:start,qifa_value:0,father:-1};//开始节点;距离开始节点长度为0 无父节点node[start].name=start;node[start].qifa_value=0;node[start].father=-1;road.push(node[start]); //加入优先队列nod temp;while(!road.empty()){temp=road.top();cout<<"当前拓展节点为: "<<city[temp.name]<<" 其子节点有:";if(temp.name==target){//目标节点int way_num=0;//路段数way.push(temp);nod i=temp;while(way.top().name!=start){//将父节点压入站,达到顺序输出的目的,直到栈顶元素是开始节点为止i=node[i.father];// 不要写成temp.father  debug了3个小时way.push(i);}cout<<endl<<endl<<"一致代价搜索找到目标节点,路径如下:"<<endl;while(!way.empty()){i=way.top();way.pop();cout<<city[i.name];if(i.name!=target){//不是目标节点时输出符号 --(cost)--》cout<<"--("<<Graph[i.name][way.top().name]<<")-->";//将线路的cost打印出来sum_cost+=Graph[i.name][way.top().name];//总价值变化+每条路线的costway_num++;}}cout<<endl<<"该路径的总消耗为: "<<sum_cost<<'\t'<<"一共经过了"<<way_num<<"个路段"<<endl;cout<<"用该搜索算法找到该路径共访问的节点个数为:"<<node_num<<"个"<<endl<<endl;sum_cost=0,node_num=0;//清零,下一个算法好直接用break; //输出一条路径后就结束}node_num++;road.pop();flag[temp.name]=visited;for(int i=0;i<20;i++){ //不是目标 搜索当前所有的子节点if(Graph[temp.name][i]>=0&&flag[i]!=visited){  //能到达且未访问node[i].name=i;node[i].qifa_value=Graph[temp.name][i]+temp.qifa_value;//父节点的已花代价+本身代价node[i].father=temp.name;cout<<city[i];road.push(node[i]);}}cout<<endl;}}int main() {init();//初始化 sum_cost=0,node_num=0;stack<int> rec;int sign[20];memset(sign,not_visit,sizeof(sign));UCS_Romania(sign);//一致代价搜索 return 0;
}
一致代价输出结果:
当前拓展节点为: A 其子节点有:STZ
当前拓展节点为: Z 其子节点有:O
当前拓展节点为: T 其子节点有:L
当前拓展节点为: S 其子节点有:FOR
当前拓展节点为: O 其子节点有:
当前拓展节点为: R 其子节点有:CP
当前拓展节点为: L 其子节点有:M
当前拓展节点为: F 其子节点有:B
当前拓展节点为: O 其子节点有:
当前拓展节点为: M 其子节点有:D
当前拓展节点为: P 其子节点有:BC
当前拓展节点为: C 其子节点有:D
当前拓展节点为: D 其子节点有:
当前拓展节点为: B 其子节点有:一致代价搜索找到目标节点,路径如下:
A--(140)-->S--(80)-->R--(97)-->P--(101)-->B
该路径的总消耗为: 418   一共经过了4个路段
用该搜索算法找到该路径共访问的节点个数为:13个

考虑贪婪优先搜索

键值为到目的地的直线距离(可以自己给出):也有如下的距离信息:

贪婪优先代码

该与一直代价策略的不同在于,需要给他提供一些信息,这里是到目标节点的直线距离。所以是有信息的搜索策略。

nod node[20]; //下面三种式搜索都要用到排序 使用优先队列实现排序
priority_queue<nod>road;//优先队列
stack<nod> way;
int h[20] ={366,0,160,242,161,178,77,151,226,244,241,234,380,98,193,253,329,80,199,374 };//直线距离,用于启发式搜索 顺序为表对应的顺序
void GFS_Romania(int *flag) {memset(node,-1,20*sizeof(nod));//node[start]={name:start,qifa_value:0,father:-1};//开始节点;距离开始节点长度为0 无父节点node[start].name=start;node[start].qifa_value=h[start];node[start].father=-1;road.push(node[start]); //加入优先队列nod temp;while(!road.empty()) {temp=road.top();cout<<"当前拓展节点为: "<<city[temp.name]<<" 其子节点有:";node_num++;if(temp.name==target) { //目标节点int way_num=0;//路段数way.push(temp);nod i=temp;while(way.top().name!=start) { //将父节点压入站,达到顺序输出的目的,直到栈顶元素是开始节点为止i=node[i.father];// 不要写成temp.father  debug了3个小时way.push(i);}cout<<endl<<endl<<"贪婪优先搜索找到目标节点,路径如下:"<<endl;while(!way.empty()) {i=way.top();way.pop();cout<<city[i.name];if(i.name!=target) { //不是目标节点时输出符号 --(cost)--》cout<<"--("<<Graph[i.name][way.top().name]<<")-->";//将线路的cost打印出来sum_cost+=Graph[i.name][way.top().name];//总价值变化+每条路线的costway_num++;}}cout<<endl<<"该路径的总消耗为: "<<sum_cost<<'\t'<<"一共经过了"<<way_num<<"个路段"<<endl;cout<<"用该搜索算法找到该路径共访问的节点个数为:"<<node_num<<"个"<<endl<<endl;sum_cost=0,node_num=0;//清零,下一个算法好直接用break; //输出一条路径后就结束}road.pop();flag[temp.name]=visited;for(int i=0; i<20; i++) { //不是目标 搜索当前所有的子节点if(Graph[temp.name][i]>=0&&flag[i]!=visited) { //能到达且未访问node[i].name=i;node[i].qifa_value=h[i];node[i].father=temp.name;cout<<city[i];road.push(node[i]);}}cout<<endl;}
}
int main() {init();//初始化sum_cost=0,node_num=0;stack<int> rec;int sign[20];memset(sign,not_visit,sizeof(sign));GFS_Romania(sign);//一致代价搜索return 0;
}
贪婪优先输出结果:
当前拓展节点为: A 其子节点有:STZ
当前拓展节点为: S 其子节点有:FOR
当前拓展节点为: F 其子节点有:B
当前拓展节点为: B 其子节点有:贪婪优先搜索找到目标节点,路径如下:
A--(140)-->S--(99)-->F--(211)-->B
该路径的总消耗为: 450   一共经过了3个路段
用该搜索算法找到该路径共访问的节点个数为:4个

考虑A*优先搜索

代码实现与一致代价和贪婪优先相似,只需修改键值为 已花费的cost+直线距离值
注意由于 父节点的key值
每个节点的key值都增加了由其父节点到该节点的cost,故要先减去这个cost,才是从起点到父节点已花费的cost,再加到本节点的直线距离才是key值

代码


nod node[20]; //下面三种式搜索都要用到排序 使用优先队列实现排序
priority_queue<nod>road;//优先队列
stack<nod> way;void ASS_Romania(int *flag) {memset(node,-1,20*sizeof(nod));//node[start]={name:start,qifa_value:0,father:-1};//开始节点;距离开始节点长度为0 无父节点node[start].name=start;node[start].qifa_value=h[start];node[start].father=-1;road.push(node[start]); //加入优先队列nod temp;while(!road.empty()) {temp=road.top();cout<<"当前拓展节点为: "<<city[temp.name]<<" 其子节点有:";if(temp.name==target) { //目标节点int way_num=0;//路段数way.push(temp);nod i=temp;while(way.top().name!=start) { //将父节点压入站,达到顺序输出的目的,直到栈顶元素是开始节点为止i=node[i.father];// 不要写成temp.father  debug了3个小时way.push(i);}cout<<endl<<endl<<"A*搜索找到目标节点,路径如下:"<<endl;while(!way.empty()) {i=way.top();way.pop();cout<<city[i.name];if(i.name!=target) { //不是目标节点时输出符号 --(cost)--》cout<<"--("<<Graph[i.name][way.top().name]<<")-->";//将线路的cost打印出来sum_cost+=Graph[i.name][way.top().name];//总价值变化+每条路线的costway_num++;}}cout<<endl<<"该路径的总消耗为: "<<sum_cost<<'\t'<<"一共经过了"<<way_num<<"个路段"<<endl;cout<<"用该搜索算法找到该路径共访问的节点个数为:"<<node_num<<"个"<<endl<<endl;sum_cost=0,node_num=0;//清零,下一个算法好直接用break; //输出一条路径后就结束}node_num++;road.pop();flag[temp.name]=visited;for(int i=0; i<20; i++) { //不是目标 搜索当前所有的子节点if(Graph[temp.name][i]>=0&&flag[i]!=visited) { //能到达且未访问node[i].name=i;node[i].qifa_value=Graph[temp.name][i]+temp.qifa_value+h[i]-h[temp.name];//f=h+g 其中 g=上一个的启发值-上一个的h node[i].father=temp.name;//    flag[i]=visited;cout<<city[i];road.push(node[i]);}}cout<<endl;}
}
int main() {init();//初始化sum_cost=0,node_num=0;stack<int> rec;int sign[20];memset(sign,not_visit,sizeof(sign));ASS_Romania(sign);//一致代价搜索return 0;
}
A*输出结果:
当前拓展节点为: A 其子节点有:STZ
当前拓展节点为: S 其子节点有:FOR
当前拓展节点为: R 其子节点有:CP
当前拓展节点为: P 其子节点有:BC
当前拓展节点为: F 其子节点有:B
当前拓展节点为: B 其子节点有:A*搜索找到目标节点,路径如下:
A--(140)-->S--(80)-->R--(97)-->P--(101)-->B
该路径的总消耗为: 418   一共经过了4个路段
用该搜索算法找到该路径共访问的节点个数为:5个

性能对比图

算法为博主手工码出,难免有错误之处,请留言更正!

人工智能导论罗马尼亚问题实验一搜索算法C++实现详解相关推荐

  1. 人工智能导论——A*算法实验

    一.实验目的: 熟悉和掌握启发式搜索的定义.估价函数和算法过程,并利用A*算法求解N数码难题,理解求解流程和搜索顺序. 二.实验原理: A*算法是一种启发式图搜索算法,其特点在于对估价函数的定义上.对 ...

  2. [Python人工智能] 十二.循环神经网络RNN和LSTM原理详解及TensorFlow编写RNN分类案例

    从本专栏开始,作者正式开始研究Python深度学习.神经网络及人工智能相关知识.前一篇讲解了TensorFlow如何保存变量和神经网络参数,通过Saver保存神经网络,再通过Restore调用训练好的 ...

  3. DSP28335软件实验研究--DA_AD模块功能详解

    选择实验板为00ic_DSP_TMS320F28335,仿真器为100v3,编译器为ccsv6.1 关于28335的DA输出模块,主要硬件由DSP和TLV5620组成,DSP提供了SIMO和SCLK. ...

  4. 广度优先搜索算法带图详解

    1.前言 广度优先搜索https://so.csdn.net/so/search?q=%E5%B9%BF%E5%BA%A6%E4%BC%98%E5%85%88%E6%90%9C%E7%B4%A2&am ...

  5. 2022山东理工大学pta程序设计---实验五(一维数组)详解

    ·## 7-1 sdut- C语言实验-最值 有一个长度为n的整数序列,其中最大值和最小值不会出现在序列的第一和最后一个位置. 请写一个程序,把序列中的最小值与第一个数交换,最大值与最后一个数交换.输 ...

  6. 微机原理及应用实验——MOV指令的使用详解

    MOV指令的使用及多字节加减法程序 前言 初识MOV指令 指令格式 指令功能 MOV指令可实现以下各种传送 使用TD进行调试 1.MOV BL,08H 2.MOV CL,BL 3.MOV AX,03F ...

  7. 实验吧——隐写术之“小苹果”详解

    小苹果 链接: 题目链接:http://www.shiyanbar.com/ctf/1928 附件链接:http://ctf5.shiyanbar.com/stega/apple.png 工具:微信扫 ...

  8. 人工智能中噪声数据的产生与处理方法详解

    噪声是影响机器学习算法有效性的重要因素之一,由于实际数据集存在采集误差.主观标注以及被恶意投毒等许多因素,使得所构造的数据集中难免存在噪声 一.噪声的分类.产生原因与影响 在机器学习训练集中,存在两种 ...

  9. 图像恢复重建(浙大人工智能导论作业四)

    图像恢复重建(浙大人工智能导论作业四) 实验思路代码有很多不完善之处,仅供学习参考 如果同是NKU2021人工智能导论的同学,可以跳过这篇博客,因为会等到实验截止之后笔者才会将实验的具体代码补全. 实 ...

最新文章

  1. offsetof使用小结
  2. 推荐15个高质量学习网站,仅看一眼,就收获满满,赶紧收藏!
  3. Git 学习笔记 —— 常用命令
  4. linux配置dhcp中继服务
  5. Emlog插件:右下角添加不同时段问候语1.2
  6. 浏览器DNS_PROBE_FINISHED_NXDOMAIN报错解决办法
  7. python云计算架构开发_云计算开发一般负责什么工作呢?更偏向于运维么?
  8. 高德地图车道级导航适配OPPO Find N折叠屏手机
  9. Docker 容器资源管理,你真的学会了吗?
  10. python图像配准的原理_SIFT图像匹配及其python实现
  11. Windows 10 微信双开或多开【PC端】
  12. 阳历日期转阴历工具类
  13. html5制作波浪,技能get:用HTML5实现波浪效果
  14. 技术研发:如何突破自己的技术瓶颈期
  15. FICO 发票校验时修改统驭科目
  16. 为什么每个女生都比较避讳别人问年龄问题?于是我偷偷写了一款年龄检测器,公司同事的年龄都被我知道了~
  17. 如何做一份精致的性能测试报告
  18. 梅特卡夫法则(Metcalfe's law)
  19. ArcGIS中建筑物图形简化工具和建筑物群聚合工具的应用
  20. springboot实现企业微信机器人自动按时播报天气

热门文章

  1. python 实现对地图的点击_利用python和百度地图API实现数据地图标注的方法
  2. Flash CS5中文帮助文档CHM版
  3. mysql dbi_mysql DBI 事务控制
  4. ZED stereo camera开发入门教程(1)
  5. ITU-R BT.1886
  6. 【Pytorch深度学习实战】(12)神经风格迁移(Neural Style Transfer)
  7. 汉字转拼音 城市绑定
  8. HTML+CSS基础知识3
  9. ssm+bootsrap人力资源考勤OA人事系统-JAVA【计算机毕业设计、源码、开题报告】
  10. Java学习作息时间表