使用搜索算法實現羅馬尼亞問題的求解
#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:分析比較無信息搜索策略和有信息搜索策略。 無信息搜索算法是指算法除了問題本身定義沒有任何其他信息,有信息搜索算法是指利用給 定的知識引導能夠更有效的找到解。無信息是不包含啓發式,有信息包含了啓發式