TSP问题的模拟退火解法

版权声明:本文为博主原创文章,转载请注明出处 https://blog.csdn.net/chenlnehc/article/details/51933802

TSP问题的模拟退火解法

产生测试数据

import random as rd
n=eval(input('城市数量:'))
res=[]
for i in range(1,n):
    for j in range(i+1,n+1):
        res.append((i,j,rd.random()*100))
f=open('input.txt','w')
f.write(str(n)+' '+str(len(res))+'\n')
for i in res:
    f.write(str(i[0])+" "+str(i[1])+" "+str(i[2])+"\n")
f.close()
input('结束')

暴力法求解程序

#include<iostream>
#include<cmath>
#define N 100
#define big 99999
using namespace std;
double s[N][N];//距离矩阵 
int m,n;//m代表坐标点个数,n代表输入行数 
int temp[N];//迭代中的一组解
int res[N];//最终解 
double dist=0;

void search(int k)  
{  
    if ( k==m )   
    {
        double ndist=0;
        for(int i=1;i<m;i++){
        	ndist+=s[temp[i]][temp[i+1]];
		}
        ndist+=s[temp[m]][temp[1]];
        if(ndist<dist){
        	for(int i=0;i<=m;i++)res[i]=temp[i];
        	dist=ndist;
		}
        return;  
    }  
      
    for (int i=k; i<=m; i++)
    {     
        swap(temp[k],temp[i]);  
        search(k+1);  
        swap(temp[k],temp[i]);  
    }  
}  

int main(){
	freopen("input.txt","r",stdin);
	cin>>m>>n;
	while(n-->0){
		int i,j;
		double k;
		cin>>i>>j>>k;
		s[i][j]=s[j][i]=k;
	}
	for(int i=1;i<=m;i++){
		s[i][i]=big;
		temp[i]=i;
		dist+=s[i][i+1];
	}
	dist+=s[m][1];
	for(int i=1;i<=m;i++)temp[i]=i;//初始化
	
	for(int i=1;i<=m;i++){
		if(i!=m)
			dist+=s[temp[i]][temp[i+1]];
		else
			dist+=s[m][1];
	}
	search(1); 
	cout<<"距离:"<<dist<<endl;
	for(int i=1;i<=m;i++)cout<<res[i]<<endl;
	
	return 0; 
}


模拟退火求解程序

#include<iostream>
#include<ctime>
#include<cstdlib>
#include<cmath>
#define N 109
#define big 9999999
using namespace std;

double nowDist(double d[N][N],int temp[N],int m){
	//计算当前temp路线组合距离
	double dist=0;
	for(int i=1;i<m;i++)dist+=d[temp[i]][temp[i+1]];
	dist+=d[temp[m]][temp[1]];
	return dist;
}

int main(){

	double d[N][N];//距离矩阵 
	int temp[N];//临时地点排列顺序表
	double dist=0;//最小距离
	int n,m;//n为输入行数,m为地点个数
	int res[N];
	double mostdist=big;
		 
	//数据输入
	freopen("input.txt","r",stdin);
	cin>>m>>n;
	while(n-->0){
		int i,j;
		double k;
		cin>>i>>j>>k;
		d[i][j]=d[j][i]=k;
	}
	for(int i=1;i<=m;i++){
		d[i][i]=big;
		temp[i]=i;
		if(i!=m) dist+=d[i][i+1];
	}
	dist+=d[m][1];
	
	cout<<"初始距离: "<<dist<<endl;
	int count=40;
	while(count--){//取count次迭代的最小结果 
		double T=1;//初始温度
		double a=0.999;//退火率
		double low=1e-30;//最低温度
		long ct=0;//迭代步数
		long ctj=0;//有效迭代步数 
		srand(time(0));//随机数种子 
		long all=300000;//最大迭代次数 
		while(T>low){
			int t1=rand()%m+1,t2=rand()%m+1;//随机获得两个位置 
			if(t1!=t2){
				swap(temp[t1],temp[t2]);//交换两位置 
				double ndist=nowDist(d,temp,m);//交换后的路线总距离 
				double df=(ndist-dist);
				if(df<0){//当前解更优 
					dist=ndist;
					ctj++;
				}else if(exp(-df/T)>(rand()%100)/100.0){//大于 
						dist=ndist;
						ctj++;
				}else{
					swap(temp[t1],temp[t2]);
				}
				T*=a;//降温
			}
			ct++;
			if(ct>all)break;
		} 
		cout<<"当前最短距离:"<<dist<<endl;
		if(dist<mostdist){
			mostdist=dist;
			for(int i=1;i<=m;i++)res[i]=temp[i];
		}
	}
	cout<<"最短距离:"<<mostdist<<endl<<"路线:";
	for(int i=1;i<=m;i++){
		cout<<res[i]<<" ";
	}
	return 0;
}


猜你喜欢

转载自blog.csdn.net/chenlnehc/article/details/51933802