启发式算法之模拟退火算法 旅行商问题TSP C++实现

文章给出旅行商问题的模拟退火算法的C++实现:
环境:win7 vc6.0

头文件:

#include <iostream>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
using namespace std;

全局变量的定义:
通过修改退火速度,初始温度可以得到不同程度的解

const int nCities = 99;   //城市数量
const double SPEED = 0.98;   //退火速度
const int INITIAL_TEMP = 1000;   //初始温度
const int L = 100 * nCities;   //Markov链的长度
double length_table[nCities][nCities]; // 城市距离

解得结构:
length 旅行商最终的路径长度
path 数组旅行商依次经过的城市


struct unit{
	double length; //路径长度
	int path[nCities]; //路径
}; 

下面是用到的函数:

初始化距离矩阵:
这里使用rand()函数随机生成数据,这样会使图的入度和出度不一致,可自己优化

//初始化距离矩阵
void init_dis(){
	for(int i = 0; i < nCities; i++)
		for(int j = 0; j < nCities; j++)
			length_table[i][j] = rand() % 100; //随机生成城市距离
}

生成函数,随机产生一个初始解,这里随机选了一个开始点,然后依次构造path

//随机产生一个初始解,随机选一个初始点顺序构造path
void generate(unit &temp){
	int j = 0;
	int i = rand() % nCities;
	while(j < nCities){
		temp.path[j] = i;
		j++;
		i = (i + 1) % nCities;
	}

}

交换法生成邻居

//交换法生成邻居

void getNewSolution(unit &p){

	int i = rand() % nCities;
	int j = rand() % nCities;
	int temp = p.path[i];
	p.path[i] = p.path[j];
	p.path[j] = temp;
}

计算路径长度


//计算路径长度

void CalCulate_length(unit &p){

	int j = 0;
	p.length = 0;
	for(j = 1; j < nCities; j++){
	
		p.length += length_table[p.path[j - 1]][p.path[j]];
	}
	p.length += length_table[p.path[nCities - 1]][p.path[0]]; //最后一城市到起点

}

接受新解得规则,根据模拟退火算法有两种情况

//接受新解规则 两个情况
bool Accept(unit &bestone, unit &temp, double t){

	if(bestone.length > temp.length)
		return true;
	else{
		if((int)(exp((bestone.length - temp.length) / t) * 100) > (rand() % 101))
			return true;
	}
	return false;
}

打印解

//打印解数组
void printp(unit p){
	cout<<"旅行商的距离为:"<<p.length<<endl;
	cout<<"经过的城市依次为:"<<endl;
	for(int i = 0; i < nCities; i++)
	{
		cout<<p.path[i]<<"  ";
		if((i+1) % 10 == 0)
			cout<<endl;
	}
	cout<<endl;
	cout<<endl;
}

核心算法,TSP模拟退火的过程

//TSP模拟退火算法
void SA_TSP(){

	srand(time(0));
	int i =0;
	double r = SPEED;
	double t = INITIAL_TEMP;
	const double t_min = 0.001;
	unit temp;
	unit bestone;
	generate(temp);
	CalCulate_length(temp);
	memcpy(&bestone, &temp, sizeof(temp));
	//打印初始解
	printp(bestone);
	while(t > t_min){
	
		for(i = 0; i < L; i++){
			getNewSolution(temp);
			CalCulate_length(temp);
			if(Accept(bestone, temp, t))
				memcpy(&bestone, &temp, sizeof(unit));
			else
				memcpy(&temp, &bestone, sizeof(unit));
		}
		t *=r;//退火

	}
	//打印最终解
	printp(bestone);
	return;
}

最后是主函数

int main(){
	init_dis();//初始化距离矩阵
	SA_TSP();//打印解在函数中
	return 0;
}

程序运行结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值