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;
}