模拟退火解决TSP问题 C++实现(拷贝构造函数中动态数组的处理)

本文介绍了一个使用模拟退火算法求解旅行商问题(TSP)的C++实现。通过定义城市间的距离矩阵,随机生成初始路径,并利用2-opt局部搜索策略和模拟退火算法进行迭代优化,最终找到近似最优的旅行路线。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

main.cpp
#include "SA.h"

int main() {

    SA a(100);
    /*a.init_gragh();
    a.rand_n();
    a.SimulatedAnnealing();
    a.print_result();*/
   SA b(a);      //利用拷贝函数做assignment
   b.init_gragh();
   b.rand_n();
   b.SimulatedAnnealing();
   b.print_result();
    system("Pause");
    return 0;
}

SA.h
#ifndef SIMULATEDANNEALING_SA_H
#define SIMULATEDANNEALING_SA_H
#include <iostream>
#include <fstream>
#include <math.h>
using namespace std;

#define R_EARTH 6370 //地球半径
#define L 2000    //迭代次数
#define AT  0.99  //降温次数
#define  T  1     //初始温度

int cmp(const void *a, const void *b);

struct element{
    double x,y;   //城市坐标
    int index; //城市代号

};
struct Rand{
    int data; //数据
    int index; //序号

};
class SA {
private:
    int num_city;     //城市数目
    int best_value;   //最求路径距离
    double **arc;  //城市之间的距离
    int *best_path;  //全局最优路径
    int *cur_path;  //当前最优路径
    int *temp_2opt;  //在2opt类函数中暂时存放cur_path
    double **city_xy;  //城市坐标
    int *new_path;  //内循环最优路径;
    element *city;  //城市坐标

public:

    SA(int n);
    SA();
    SA(const SA& c);       //拷贝构造函数
    virtual ~SA();
    void init_gragh();  //初始化城市数据(求任意两个城市之间的距离)
    void rand_n();     //随机产生一条路径
    void two_opt();    //2分法产生新路径
    void SimulatedAnnealing();  //模拟退火
    void  print_result();  //输出结果
};
SA.cpp
#include "SA.h"

SA::SA(int n){
    this->num_city=n;
    this->arc= new double *[this->num_city];
    this->city_xy=new double *[2];
    this->best_path= new int[this->num_city+1];
    this->temp_2opt=new int[this->num_city+1];
    this->cur_path=new int[this->num_city+1];
    this->city=new element[this->num_city];
    this->new_path=new int[this->num_city+1];
    this->best_value=0;
    for(int i=0;i<this->num_city;i++)
    {
        this->arc[i]=new double[this->num_city];
        for(int j=0;j<this->num_city;j++)
            this->arc[i][j]=INT_MAX;
    }

    for(int i=0;i<this->num_city;i++)
    {
        this->city_xy[i]=new double [2];
        for(int j=0;j<2;j++)
            this->city_xy[i][j]=0;
    }
    fstream file("data.txt");
    if(!file.is_open())
        cout<<"文件未成功读取"<<endl;
    for(int i=0;i<this->num_city;i++)
        for(int j=0;j<2;j++)
            file>>this->city_xy[i][j];
    file.close();

    for(int i=0;i<this->num_city;++i){
        this->city[i].x=this->city_xy[i][0];
        this->city[i].y=this->city_xy[i][1];
        this->city[i].index=i;
    }

}
SA::SA(const SA &c) {
    this->num_city=c.num_city;
    this->best_value=c.best_value;

    this->best_path=new int[this->num_city+1];
    *best_path=*(c.best_path);

    this->cur_path= new int[this->num_city+1];
    *cur_path=*(c.cur_path);

    this->temp_2opt=new int[this->num_city+1];
    *temp_2opt=*(c.temp_2opt);

    this->new_path=new int[this->num_city+1];
    *new_path=*(c.new_path);

    this->arc= new double*[this->num_city];
    this->city_xy=new double*[2];

    for(int i=0;i<this->num_city;i++)
    {
        this->arc[i]=new double[this->num_city];
        for(int j=0;j<this->num_city;++j)
            this->arc[i][j]=c.arc[i][j];

        this->city_xy[i]=new double[2];//[2];
        for(int k=0;k<2;k++)
            this->city_xy[i][k]=c.city_xy[i][k];
    }

    this->city=new element[this->num_city];
    for(int i=0;i<this->num_city;i++)
    {
        this->city[i].x=this->city_xy[i][0];
        this->city[i].y=this->city_xy[i][1];
        this->city[i].index=i;
    }

}
SA::~SA() {
    delete []best_path;
    delete []cur_path;
    delete []temp_2opt;
    delete []new_path;
    for(int i=0;i<this->num_city;++i) {
        delete []this->arc[i];
    }
    for(int i=0;i<2;i++)
        delete []this->city_xy[i];
    delete []arc;
    delete []city_xy;
    delete []city;
}
void SA::init_gragh() {
    for(int i=0;i<this->num_city;i++){
        for(int j=0;j<this->num_city;j++){
            this->arc[i][j]=R_EARTH*acos(sin(this->city[i].y)*sin(this->city[j].y)+cos(this->city[i].y)*cos(this->city[j].y)*cos(this->city[j].x-this->city[i].x));
        }
    }

}
int cmp(const void *a, const void *b) {

    return ((Rand*)a)->data-((Rand*)b)->data;
}

void SA::rand_n() {
    double curent=0.00,best;
    int *temp;
    ////mento car 随机模拟1000次 选择其中最优的一条路径////
    for(int k=0;k<1000;k++) {
        srand((int) time(0));    //初始化随机数种子
        temp=new int[this->num_city+1];
        Rand *ele;
        ele = new Rand[this->num_city];

        for (int i = 0; i < this->num_city; ++i) {
            ele[i].data = rand();
            ele[i].index = i;
        }
        qsort(ele, this->num_city, sizeof(ele[0]), cmp);

        for (int i = 0; i < this->num_city; ++i) {
            temp[i]=ele[i].index;
        }
        temp[this->num_city]=temp[0];  //形成闭环
        delete[]ele;
        for (int i = 0; i < this->num_city; ++i) {
            curent = curent + this->arc[temp[i]][temp[i + 1]];
        }
        if(k==0) {
            best = curent;
            for (int i = 0; i <= this->num_city; ++i)
                this->cur_path[i]=temp[i];

        }
        else
        {
            if(curent<best) {
                best = curent;
                for (int i = 0; i <= this->num_city; ++i)
                    this->cur_path[i]=temp[i];
            }
        }
        memmove(this->temp_2opt,this->cur_path, sizeof(int)*(this->num_city+1));
        delete []temp;
    }
}

void SA::two_opt() {

    srand((int)time(0));
    int n1,n2,left,right;
    n1=rand()%this->num_city;
    do{
        n2=rand()%this->num_city;
    }while(n1==n2);

    if(n1<n2)
    {
        left=n1;
        right=n2;

    } else{
        left=n2;
        right=n1;
    }
    while(left<right){
        swap(this->temp_2opt[left],this->temp_2opt[right]);
        left++;
        right--;
    }
    this->temp_2opt[this->num_city]=this->temp_2opt[0];  //   形成闭环


}

void SA::SimulatedAnnealing() {
    int t=T;
    double best=0,curent;
    memmove(this->best_path,this->cur_path, sizeof(int)*(this->num_city+1));

    for(int i=0;i<this->num_city;++i)
        best=best+this->arc[this->cur_path[i]][this->cur_path[i+1]];
    curent=best;

    for(int i=0;i<1000;i++)
    {
        double temp_best=curent; //存放内循环最优路径距离
        double df;
        srand((int)time(0));
        ////////////////内循环//////////
        for(int j=0;j<this->num_city*this->num_city;++j)
        {

            double temp_num=0;  //存放当前路径距离
            SA::two_opt();
            for(int k=0;k<this->num_city;k++)
                temp_num=temp_num+this->arc[this->temp_2opt[k]][this->temp_2opt[k + 1]];
                //cout<<"temp_num is "<<temp_num<<endl;
            if(temp_num<curent){
                temp_best=temp_num;
                memmove(this->new_path,this->temp_2opt, sizeof(int)*(this->num_city+1));
            }
        }

        df=temp_best-curent;
        if(df<0){
            curent=temp_best;
            best=temp_best;
            memmove(this->best_path,this->new_path, sizeof(int)*(this->num_city+1));
            memmove(this->cur_path,this->new_path, sizeof(int)*(this->num_city+1));
            memmove(this->temp_2opt,this->new_path, sizeof(int)*(this->num_city+1));
        }else{
            if(exp(-df/t)>(double)rand()/RAND_MAX && exp(-df/t)<1)
            {
                curent=temp_best;
                memmove(this->cur_path,this->new_path, sizeof(int)*(this->num_city+1));
                memmove(this->temp_2opt,this->new_path, sizeof(int)*(this->num_city+1));
            }
        }

        t=t*AT;
    }
    this->best_value=best;
}

void SA::print_result() {
    cout<<"this best value is "<<this->best_value<<endl;
    for(int i=0;i<=this->num_city;i++)
        if(i<this->num_city)
            cout<<this->best_path[i]<<"->";
        else
            cout<<this->best_path[i];
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值