使用搜索算法實現羅馬尼亞問題的求解

使用搜索算法實現羅馬尼亞問題的求解

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章