求解旅行商(货郎担)问题的五种方法

1.蛮力法

#include"Graph.cpp"
#include<stdio.h>
#include<vector>
using namespace std;
int s=0;
MGraph g;
int Count=1;
vector<vector<int> >ps;
void Insert(vector<int>s,int i,vector<vector<int>> &ps1){
	vector<int>s1;
	vector<int>::iterator it;
	for(int j=0;j<i;j++){
		s1=s;
		it=s1.begin()+j;
		s1.insert(it,i);
		ps1.push_back(s1);
	}
} 
void Perm(int n){
	vector<vector<int>> ps1;
	vector<vector<int>>::iterator it;
	vector<int>s,s1;
	s.push_back(1);
	ps.push_back(s);
	for(int i=2;i<=n;i++){
		ps1.clear();
		for(it=ps.begin();it!=ps.end();it++){
			Insert(*it,i,ps1);
		}
		ps=ps1;
	} 
}
void TSP(MGraph g,int s){
	vector<int>minpath;
	int minpath=INF;
	Perm(g.n-1);
	vector<vector<int>>::reverse_iterator it;
	vector<int>apath;
	int pathlen;
	printf("起点为%d的全部路径:",s);
	for(it=ps.rbegin();it!=ps.rend();it++){
		pathlen=0;
		int initv=s;
		apath=(*it);
		for(int i=0;i<(*it).size();i++){
			pathlen+=g.edges[initv][(*it)[i]];
			initv=(*it)[i];
		}
		pathlen+=g.edges[initv][s];
		if(pathlen<INF){
			printf("%d:",Count++);
			cout<<"0->";
			for(int i=0;i<apath.size();i++){
				printf("%d->",apath[i]);
			}
			printf("%d路径长度:%d\n",0,pathlen);
			if(pathlen<minpathlen){
				minpathlen<pathlen;
				minpath=apath;
			}
		}
	}
	printf("起点为%d的最短路径\n",s);
	printf("最短路径长度:%d\n",minpathlen);
	printf("最短路径:");
	printf("0->");
	for(int i=0;i<minpath.size();i++){
		printf("%d->",minpath[i]);
	}
	cout<<"0"<<endl;
}
int main(){
	TSP(g,s);
}

2.分支限界法

#include"Graph.cpp"
#include<string.h>
#include<vector>
using namespace std;
int s;
MGraph g;
int Count=1;
vector<int>minpath;
int minpathlen=INF;

struct NodeType{
	int v,num;
	int visited[MAXV];
	int pathlen;
	vector<int>path;
	bool operator <(const NodeType &s) const{
		return pathlen>s.pathlen;
	}
};
void dispasolution(vector<int>path,int pathlen){
	cout<<Count++<<endl;
	for(int i=0;i<path.size();i++){
		printf("%2d",path[i]);
	}
	printf("路径长度",pathlen);
}
void TSP(){
	NodeType e,e1;
	priority_queue<NodeType>qu;
	e.v=0;
	e.pathlen=0;
	e.path.push_back(0);
	e.num=1;
	memset(e.visited,0,sizeof(e.visited));
	e.visited[0]=1;
	qu.push(e);
	while(!qu.empty()){
		e=qu.top();
		qu.pop();
		if(e.num==g.n){
			if(g.edges[e.v][s]!=0&&g.edges[e.v][s]!=INF){
				e.path.push_back(s);
				e.pathlen+=g.edges[e.v][s];
				dispasolution(e.path,e.pathlen);
				if(e.pathlen<minpathlen){
					minipathlen=e.pathlen;
					minpath=e.path;
				}
			}
		}else {
			for(int j=1;j<g.n;j++){
				if(g.edges[e.v][j]!=0&&g.edges[e.v][j]!=INF){
					if(e.visited[j]==1) continue;
					e1.v=j;
					e1.num=e.num+1;
					e1.path=e.path;
					e1.path.push_back(j);
					e1.pathlen=e.pathlen+g.edges[e.v][j];
					for(int j=0;j<g.n;j++){
						e1.visited[i]=e.visited[i];
					}
					if(e1.pathlen<minpathlen){
						e1.visited[j]=1;
						qu.push(e1);
					}
				}
			}	
		}
	}
}
int main(){
	TSP();
}

3.回溯法

void TSP(SET V,int i,vector<int>path,int pathlen){
	int prev;
	if(path.size()>0){
		prev=path.back();
	}
	path.push_back(i);
	pathlen+=g.edges[prev][i];
	if(V.size()==0) {
		if(g.edges[i][s]!=0&&g.edges[i][s]!=INF){
			path.push_back(0);
			pathlen+=g.edges[i][s];
			dispasolution(path,pathlen);
			if(pathlen<minpathlen){
				minpathlen=pathlen;
				minpath=path;
			}
		}
	}else {
		SET::iterator it;
		for(it=V.begin();it!=V.end();it++){
			SET tmpV=V;
			int j=*it;
			tmpV.erase(j);
			if(pathlen<minpathlen) 
				TSP(tmpV,j,path,pathlen);
		}
	}
}

4.贪心法

void TSP(MGraph g){
	int i,j,k;
	int minj,minedge;
	bool find;
	vector<int>minpath;
	int minpathlen=0;
	minpath.push_back(0);
	i=0;
	while(minpath.size()!=g.n){
		find=false;
		minedge=INF;
		for(j=1;j<g.n;j++){
			if(g.edges[i][j]!=0&&g.edges[i][j]!=INF){
				k=0;
				while(k<minpath.size()&&j!=minpath[k]){
					k=0;
					while(k<minpath.size()&&j!=minpath[k]) k++;
					if(k==minpath.size()){
						if(g.edges[i][j]<minedge){
							minedge=g.edges[i][j];
							minj=j;
						}
					}
				}
			}
		}
		minpath.push_back(minj);
		minpathlen+=minedge;
		i=minj;
	}
	minpath.push_back(0);
	minpathlen+=g.edges[minj][0];
	
}

5.动态规划法

typedef set<int>SET;
int s=0;
MGraph g;
int dp[1<<MAX][MAX];
int minpathlen;
vector<int>minpath;
void solve(){
	int n=g.n-1;
	memset(dp,0,sizeof(dp));
	for(int V=0;V<=(1<<n)-1;V++){
		for(int i=1;i<=n;i++){
			if(V&(1<<(i-1))){
				if(V==(1<<i-1)) dp[V][i]=edges[0][i];
				else {
					dp[V][i]=INF;
					for(int j=1;j<=n;j++){
						if(V&(1<<(j-1))&&i!=j){
							dp[V][i]=min(dp[V][i],dp[V^(1<<(i-1))][j]+g.edges[j][i]);
						}
					}
				}
			}
		}
	}
}
  • 1
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值