使用搜索算法实现罗马尼亚问题的求解
#include<iostream>
#include<stack>
#include<queue>
#include<fstream>
using namespace std;
struct node{
int city;
int cost;
node(){
}
node(int mcity,int mcost){
city=mcity;
cost=mcost;
}
bool operator >(const node &s)const{
return cost<s.cost;//最小值优先
}
bool operator <(const node &s)const{
return cost>s.cost;//最小值优先
}
bool operator ==(const node &s)const{
return cost==s.cost;//最小值优先
}
};
int depth=1,iter=1; //标记位,如果搜索到了目标城市,则终止,无需搜索全部路径
int sum=0,num=0; //记录代价值
void BFS(int begin,int start1,int *sign,int father[],int finish,string city[],int street[][20])
{
queue<int> Q;
cout<<"宽度优先搜索的路径为:"<<city[begin];
for(int i=0;i<20;i++) //扩展可以扩展的结点,并加入队列依次扩展
if(street[begin][i]>0)
{
if(sign[i]==0)
{
sign[i]=1;
Q.push(i);
father[i]=begin; //更新父结点的值
}
}
while(!Q.empty()) //循环扩展,直到所有结点都被扩展
{
int x=Q.front();
Q.pop();
if(x==finish)
{
stack<int> temp1;
int tmp=12;
while(tmp!=2)
{
temp1.push(tmp);
tmp=father[tmp]; //依据父结点,递推倒序输出即为路径
}
int n=0;
int t=0;
while(!temp1.empty()){
cout<<"->"<<city[temp1.top()];
if(n==0){
sum+=street[start1][temp1.top()];
n++;
t=temp1.top();
}
else{
sum+=street[t][temp1.top()];
t=temp1.top();
}
temp1.pop();
}
cout<<endl<<"路径耗散为:"<<sum<<endl;
cout<<"时间复杂度为:"<<num<<endl;
break;
}
for(int i=0;i<20;i++)
if(street[x][i]>0)
{
if(sign[i]==0)
{
num++;
sign[i]=1;
Q.push(i);
father[i]=x;
}
}
}
}
void DFS(int start,int start1,stack<int> temp,int *sign,int finish,string city[],int street[][20])
{
if(start==finish) //如果搜到了目标
{
depth=0;
cout<<"深度优先的路径为:";
stack<int> temp1;
while(!temp.empty())
{
temp1.push(temp.top());
temp.pop();
}
cout<<city[start1];
int n=0;
int t=0;
while(!temp1.empty())
{
cout<<"->"<<city[temp1.top()];
if(n==0){
sum+=street[start1][temp1.top()];
n++;
t=temp1.top();
}
else{
sum+=street[t][temp1.top()];
t=temp1.top();
}
temp1.pop();
}
cout<<endl;
cout<<"路径耗散为:"<<sum<<endl;
cout<<"时间复杂度为:"<<num<<endl;
return;
}
for(int i=0;i<20;i++) //找到可以扩展的结点,并递归扩展
{
if(street[start][i]>0 &&depth)
{
temp.push(i);
if(sign[i]==0)
{
num++;
sign[i]=1;
DFS(i,start1,temp,sign,finish,city,street);
sign[i]=0;
}
temp.pop();
}
}
}
void IDS(int start,int start1,stack<int> temp,int *sign,int deep,int now,int finish,string city[],int street[][20])
{
sign[start]=1;
if(start==finish) //如果搜到了目标,停止搜索,计算代价和路径
{
iter=0;
cout<<"迭代加深的深度优先搜索路径为:";
stack<int> temp1;
while(!temp.empty())
{
temp1.push(temp.top());
temp.pop();
}
cout<<city[start1];
int n=0;
int t=0;
while(!temp1.empty())
{
cout<<"->"<<city[temp1.top()];
if(n==0){
sum+=street[start1][temp1.top()];
n++;
t=temp1.top();
}
else{
sum+=street[t][temp1.top()];
t=temp1.top();
}
temp1.pop();
}
cout<<endl;
cout<<"路径耗散为:"<<sum<<endl;
cout<<"时间复杂度为:"<<num<<endl;
return;
}
for(int i=0;i<20;i++) //如果找到了可以扩展的结点,那么扩展它
{
if(street[start][i]>0&&iter)
{
temp.push(i);
if(sign[i]==0)
{
sign[i]=1;
if(now<deep) //如果还没有超过深度限制,那么可以继续递归下一层
{
num++;
now++;
IDS(i,start1,temp,sign,deep,now,finish,city,street);
now--;
}
sign[i]=0;
}
temp.pop();
}
}
}
void UCS(int begin,int start1,int *sign,int father[],int finish,string city[],int street[][20],int gred[])
{
priority_queue<node>Q;
int s,c;
cout<<"一致代价搜索路径为:"<<city[begin];
for(int i=0;i<20;i++) //扩展可以扩展的结点,并加入队列依次扩展
if(street[begin][i]>0)
{
if(sign[i]==0)
{
sign[i]=1;
Q.push(node(i,street[begin][i]));
father[i]=begin; //更新父结点的值
}
}
while(!Q.empty()) //循环扩展,直到所有结点都被扩展
{
struct node Node;
Node=Q.top();
Q.pop();
if(Node.city==finish)
{
stack<int> temp1;
int tmp=12;
while(tmp!=2)
{
temp1.push(tmp);
tmp=father[tmp]; //依据父结点,递推倒序输出即为路径
}
int n=0;
int t=0;
while(!temp1.empty()){
cout<<"->"<<city[temp1.top()];
if(n==0){
sum+=street[start1][temp1.top()];
n++;
t=temp1.top();
}
else{
sum+=street[t][temp1.top()];
t=temp1.top();
}
temp1.pop();
}
cout<<endl<<"路径耗散为:"<<sum<<endl;
cout<<"时间复杂度为:"<<num<<endl;
break;
}
for(int i=0;i<20;i++)
if(street[Node.city][i]>0)
{
if(sign[i]==0)
{
num++;
sign[i]=1;
Q.push(node(i,street[Node.city][i]+Node.cost));
if(i==finish)
sign[i]=0;
father[i]=Node.city;
}
}
}
}
void GBS(int begin,int start1,int *sign,int father[],int finish,string city[],int street[][20],int gred[])
{
priority_queue<node>Q;
int s,c;
cout<<"贪婪最佳搜索路径为:"<<city[begin];
for(int i=0;i<20;i++) //扩展可以扩展的结点,并加入队列依次扩展
if(street[begin][i]>0)
{
if(sign[i]==0)
{
sign[i]=1;
Q.push(node(i,gred[i]));
father[i]=begin; //更新父结点的值
}
}
while(!Q.empty()) //循环扩展,直到所有结点都被扩展
{
struct node Node;
Node=Q.top();
Q.pop();
if(Node.city==finish)
{
stack<int> temp1;
int tmp=12;
while(tmp!=2)
{
temp1.push(tmp);
tmp=father[tmp]; //依据父结点,递推倒序输出即为路径
}
int n=0;
int t=0;
while(!temp1.empty()){
cout<<"->"<<city[temp1.top()];
if(n==0){
sum+=street[start1][temp1.top()];
n++;
t=temp1.top();
}
else{
sum+=street[t][temp1.top()];
t=temp1.top();
}
temp1.pop();
}
cout<<endl<<"路径耗散为:"<<sum<<endl;
cout<<"时间复杂度为:"<<num<<endl;
break;
}
for(int i=0;i<20;i++)
if(street[Node.city][i]>0)
{
if(sign[i]==0)
{
num++;
sign[i]=1;
Q.push(node(i,gred[i]));
//if(i==finish)
//sign[i]=0;
father[i]=Node.city;
}
}
}
}
void ASS(int begin,int start1,int *sign,int father[],int finish,string city[],int street[][20],int gred[])
{
priority_queue<node>Q;
int s,c;
cout<<"A*搜索路径为:"<<city[begin];
for(int i=0;i<20;i++) //扩展可以扩展的结点,并加入队列依次扩展
if(street[begin][i]>0)
{
if(sign[i]==0)
{
sign[i]=1;
Q.push(node(i,gred[i]+street[begin][i]));
father[i]=begin; //更新父结点的值
}
}
while(!Q.empty()) //循环扩展,直到所有结点都被扩展
{
struct node Node;
Node=Q.top();
Q.pop();
if(Node.city==finish)
{
stack<int> temp1;
int tmp=12;
while(tmp!=2)
{
temp1.push(tmp);
tmp=father[tmp]; //依据父结点,递推倒序输出即为路径
}
int n=0;
int t=0;
while(!temp1.empty()){
cout<<"->"<<city[temp1.top()];
if(n==0){
sum+=street[start1][temp1.top()];
n++;
t=temp1.top();
}
else{
sum+=street[t][temp1.top()];
t=temp1.top();
}
temp1.pop();
}
cout<<endl<<"路径耗散为:"<<sum<<endl;
cout<<"时间复杂度为:"<<num<<endl;
break;
}
for(int i=0;i<20;i++)
if(street[Node.city][i]>0)
{
if(sign[i]==0)
{
num++;
sign[i]=1;
Q.push(node(i,gred[i]+street[Node.city][i]+Node.cost));
if(i==finish)
sign[i]=0;
father[i]=Node.city;
}
}
}
}
int main()
{
ifstream ff("1.txt");
string city[20];//城市名
for(int i=0;i<20;i++){
ff>>city[i];
}
int street[20][20];//路径
for(int i=0;i<20;i++){
for(int j=0;j<20;j++){
ff>>street[i][j];
}
}
int gred[20];//启发式
for(int i=0;i<20;i++){
ff>>gred[i];
}
ff.close();
int start,finish; //起始城市为Ared,终止城市为Bucharest
cout<<"请输入开始城市和结束城市,当前题目开始城市为2,结束城市为12"<<endl;
cin>>start>>finish;
int a;
cout<<"请选择搜索方法1~6"<<endl;
while(1){
cin>>a;
sum=0,num=0;
stack<int> p;
int father[20]={0};
int sign[20]={0};
int deep=0;
//当前结点已经访问,避免死循环
switch(a){
case 1:sign[start]=1;BFS(start,start,sign,father,finish,city,street);break;
case 2:sign[start]=1;DFS(start,start,p,sign,finish,city,street);break;
case 3:sign[start]=1;UCS(start,start,sign,father,finish,city,street,gred);break;
case 4:
while(iter)
{
deep++;
stack<int> ptemp;
int sign_temp[20]={0};
sign_temp[start]=1;
IDS(start,start,ptemp,sign_temp,deep,0,finish,city,street);
}
break;
case 5:sign[start]=1;GBS(start,start,sign,father,finish,city,street,gred);break;
case 6:sign[start]=1;ASS(start,start,sign,father,finish,city,street,gred);break;
default:cout<<"error"<<endl;break;
}
}
return 0;
}
1:宽度优先搜索,深度优先搜索,一致代价搜索,迭代加深的深度优先搜索算法哪种方法最 优?一致代价是最优的,因为它拓展的是路径消耗 g(n)最小的结点 n.而深度优先的搜索算法,当 一条路径找到解就不会执行了,这种情况下找到解可能会非常糟糕,而宽度优先搜索和迭代 加深的深度优先搜索算法找到的是最浅深度的解,没有对代价大小进行比较,所以也不是最 优的。
2:贪婪最佳优先搜索和 A搜索那种方法最优? A搜索算法是最优的。这两种算法都是有信息的搜索。贪婪最佳优先算法试图拓展离目标最 近的结点,它只用启发式信息 f(n)=h(n),它与深度优先算法类似,找到的不一定是最优的。而 A*算法,它对结点的评价结合了 g(n)和 h(n),f(n)=g(n)+h(n)经过结点 n 的最小代价解的估计代 价。满足一致性和可采纳性所以是最优的。
3:分析比较无信息搜索策略和有信息搜索策略。 无信息搜索算法是指算法除了问题本身定义没有任何其他信息,有信息搜索算法是指利用给 定的知识引导能够更有效的找到解。无信息是不包含启发式,有信息包含了启发式