用遗传算法解决TSP问题

浅谈遗传算法:https://www.cnblogs.com/AKMer/p/9479890.html

Description

\(mzf\)在踏上寻找\(oxy\)的路程之后不小心碰到了大魔王\(fater\)。

大魔王看了看\(mzf\)的命运,心生怜悯,便给\(mzf\)和自己做一个交换的机会。

这个交换是这样的:

由于\(oxy\)不知在天涯海角,\(mzf\)的要找到实在是太难了。所以大魔王愿意把\(mzf\)和\(oxy\)同时扔到一个迷宫(\(n\)个点的完全无向图)里,但是\(oxy\)在哪个点上是未知的。

\(mzf\)初始在\(1\)号点。\(1\)号点上有迷宫出口,打开出口需要遍历整张图拿到全部点上的钥匙。\(mzf\)要将自己日思夜念的\(oxy\)从迷宫深处的不知方位的点带出来就必须遍历所有的点。然而大魔王并不愿意一昧的帮助\(mzf\),他说如果\(mzf\)重复经过一个点或者走过的路程不是最短的环那么他和\(oxy\)将永远无法逃出迷宫。

\(mzf\)想见\(oxy\),不管三七二十一便答应了大魔王。在进去之前大魔王给了他一张地图,然后便将\(mzf\)扔进了迷宫并且关上了入口。

\(mzf\)在黑暗的迷宫里才明白过来,自己虽然是\(OIer\),但是自己的\(Computer\)似乎被大魔王没收了。于是乎,作为同是\(OIer\)的挚友,他打电话告诉你这件事情并且希望你能帮助他。他将地图以一个矩阵的形式给了你。由于他实在是太想念\(oxy\)了,但他也不好意思太麻烦你,所以他希望你能在\(1s\)内帮他算出最短路径。只要你告诉他正确的答案,出题人就会告诉他怎么走才是最优的。

Input

输入一共\(n+1\)行

第一行一个数字\(n\)

接下来一个\(n\)阶矩阵,\(dis[i][j]\)记录\(i,j\)之间的距离

Output

输出仅一行

一个数字表示最短的哈密尔顿环的长度

Sample Input

4

0 1 2 3

1 0 2 3

2 2 0 3

3 3 3 0

Sample Output

9

\(n\leqslant100,dis[i][j]\leqslant100000\)

我自己造的数据:https://files.cnblogs.com/files/AKMer/TSP.zip

由于爆搜跑得慢所以只造了\(n\leqslant12\)的数据

首先题目意思是要你求一个无向完全图中最短哈密尔顿环的长度。

对于这题用遗传算法,估价函数可以设成一个最长环长度减去当前染色体所表示的环的长度,那么环长度越短,适应性就会越高。

然后交换操作要进行一些改进。因为直接交换会使得某个染色体中重复出现某个点(会导致\(mzf\)和\(oxy\)不能逃出迷宫!!)。于是乎我们就将串与串之间交换改成在一条染色体上交换两个位置,和变异一起做了。

就大功告成了。如果是提答题的话遗传代数和变异次数可以设置多一点,如果是想在传统题上骗分记得不要设置太高导致\(TLE\)。

一开始\(srand(time(0))\)狂\(Wa\)不止:

难道就只能这样了吗?不!

后来我\(srand\)我俩的名字首字母就\(A\)掉了哈哈哈

时间复杂度:\(O(欧洲人)\)

空间复杂度:\(O(n)\)

代码如下:

#include <ctime>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int inf=10000005;
const int maxn=105;

int dis[maxn][maxn];//dis存距离
int f[maxn],f1[maxn],g[maxn];//f存适应度函数,f1缓存f,g存确定性选择法下选几次
int n,low=inf,mx_f,tim,chr_cnt=100;//low存当前种群中最短长度,tim存low持续不变了多少代,chr_cnt存染色体条数,mx_f存当前种群最长环长度

int read() {
    int x=0,f=1;char ch=getchar();
    for(;ch<‘0‘||ch>‘9‘;ch=getchar())if(ch==‘-‘)f=-1;
    for(;ch>=‘0‘&&ch<=‘9‘;ch=getchar())x=x*10+ch-‘0‘;
    return x*f;
}//快读

int random(int limit) {
    return rand()%limit;
}//rand一个[0,limit)范围的数字

struct Chromosome {
    int gene[maxn];//存环上点的顺序

    int calc() {
        int res=0;
        for(int i=2;i<=n;i++)
            res+=dis[gene[i-1]][gene[i]];
        return res+dis[gene[n]][gene[1]];//依次累加环上的边
    }//算适应度函数

    void Initialization() {
        for(int i=1;i<=n;i++)
            gene[i]=i;
        random_shuffle(gene+1,gene+n+1);
    }//初始化
}chr[maxn],new_chr[maxn],ans;//chr存当前种群,new_chr存下一代种群,ans存方案,最后用于统计答案

void select() {//选择
    for(int i=1;i<=chr_cnt;i++) {
        f[i]=chr[i].calc();//算最短路
        mx_f=max(mx_f,f[i]);
        if(f[i]<low) {
            low=f[i],tim=0;
            ans=chr[i];//如果更新low就更新全局答案
        }
    }
    tim++;int res=0,cnt=0;//res存总适应度,cnt存下一代染色体条数
    for(int i=1;i<=chr_cnt;i++)
        f[i]=mx_f-f[i]+1,res+=f[i];//更新适应度,累加到res里
    for(int i=1;i<=chr_cnt;i++)
        g[i]=1.0*f[i]/res*chr_cnt,f1[i]=f[i],cnt+=g[i];//算g[i],将f缓存到f1里
    while(cnt<chr_cnt)g[random(chr_cnt)+1]++,cnt++;//没有选满就继续选
    cnt=0;
    for(int i=1;i<=chr_cnt;i++) {
        for(int j=1;j<=g[i];j++) {
            new_chr[++cnt]=chr[i];
            f[cnt]=f1[i];//同步更新适应度
            if(cnt==chr_cnt)break;
        }
        if(cnt==chr_cnt)break;//满了就不加了
    }//模拟选择过程
    for(int i=1;i<=chr_cnt;i++)
        chr[i]=new_chr[i];//更新chr
}

void variety() {//变异
    for(int i=1;i<=500*chr_cnt;i++) {//不用交换的话就多变异几次
        int u=random(chr_cnt)+1,l=random(n)+1,r=random(n)+1;//u是即将变异的染色体,l和r是要交换的位置
        Chromosome tmp=chr[u];swap(tmp.gene[l],tmp.gene[r]);
        int res=tmp.calc();//tmp缓存变异后的染色体
        if(res<chr[u].calc()) {//如果编译后更优了就变异
            chr[u]=tmp;
            f[u]=mx_f-res;//更新染色体和适应度
        }
    }
}

void Genetic() {
    while(1) {
        select();
        if(tim>200)return;//超过200代不变就算正确了
        variety();
    }//遗传过程
}

int main() {
    srand(‘o‘+‘x‘+‘y‘+‘m‘+‘z‘+‘f‘);//她叫oxy,我是mzf
    n=read();
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            dis[i][j]=read();//读入
    for(int i=1;i<=chr_cnt;i++)
        chr[i].Initialization();//初始化祖先种群
    Genetic();//遗传
    printf("%d\n",ans.calc());//输出
    return 0;
}

原文地址:https://www.cnblogs.com/AKMer/p/9496777.html

时间: 2024-10-10 04:50:22

用遗传算法解决TSP问题的相关文章

遗传算法解决TSP问题

1实验环境 实验环境:CPU [email protected],内存6G,windows7 64位操作系统 实现语言:java (JDK1.8) 实验数据:TSPLIB,TSP采样实例库中的att48数据源 数据地址:http://comopt.ifi.uni-heidelberg.de/software/TSPLIB95/tsp/att48.tsp.gz TSPLIB是一个从各种来源和各种类型中产生的TSP及其相关问题的采样实例库,这里选取TSP采样实例库中的att48数据源,最优值为106

tsp问题——遗传算法解决

TSP问题最简单的求解方法是枚举法.它的解是多维的.多局部极值的.趋于无穷大的复杂解的空间,搜索空间是n个点的所有排列的集合,大小为(n-1)!.可以形象地把解空间看成是一个无穷大的丘陵地带,各山峰或山谷的高度即是问题的极值.求解TSP,则是在此不能穷尽的丘陵地带中攀登以达到山顶或谷底的过程. 这一篇将用遗传算法解决TSP问题. 1)评价.这个评价算法应该比较简单了,就是找计算总距离,小的为优.目标函数转化为适应度函数可以取倒数. 2)突变.为了防止重复访问,不能随机的进行突变.因为每个城市只能

蚁群算法解决TSP问题

一.论述 1.算法来源 蚁群算法的基本原理来源于自然界蚂蚁觅食的最短路径原理,根据昆虫学家的观察,发现自然界的蚂蚁虽然视觉不发达,但它可以在没有任何提示的情况下找到从食物源到巢穴的最短路径,并且能在环境发生变化(如原有路径上有了障碍物)后,自适应地搜索新的最佳路径. 2.单个蚂蚁寻找路径 正反馈: 单个的蚂蚁为了避免自己迷路,它在爬行时,同时也会释放一种特殊的分泌物--信息素(Pheromone),而且它也能觉察到一定范围内的其它蚂蚁所分泌的信息素,并由此影响它自己的行为.当一条路上的信息素越来

遗传算法求解TSP源码及解析

1.算法效果 图 1?1算法效果1 图 1?2算法效果2 2.原理说明 TSP问题是指假设有一个旅行商人要拜访n个城市,他必须选择所要走的路径,路径的限制是每个城市只能拜访一次,而且最后要回到原来出发的城市.路径的选择目标是要求得的路径路程为所有路径之中的最小值.本文使用遗传算法解决att30问题,即30个城市的旅行商问题. 旅行商问题是一个经典的组合优化问题.一个经典的旅行商问题可以描述为:一个商品推销员要去若干个城市推销商品,该推销员从一个城市出发,需要经过所有城市后,回到出发地.应如何选择

基于遗传算法求解TSP问题(Java界面)

近期为做展示,改写了一个遗传算法求TSP的Java界面版,思路代码和 http://blog.csdn.net/wangqiuyun/article/details/12838903 这篇文章思路是一样的,追加了Java用Graphics画点及画线做路径展示,展示部分做得比較粗糙,须要的拿走,效果图例如以下. 下载地址:http://download.csdn.net/detail/wangqiuyun/7406201 另C#界面版:http://blog.csdn.net/wangqiuyun

【高级算法】遗传算法解决3SAT问题(C++实现)

转载请注明出处:http://blog.csdn.net/zhoubin1992/article/details/46910079 1 SAT问题描写叙述 命题逻辑中合取范式 (CNF) 的可满足性问题 (SAT)是当代理论计算机科学的核心问题, 是一典型的NP 全然问题.在定义可满足性问题SAT之前,先引进一些逻辑符号. 一个 SAT 问题是指: 对于给定的 CNF 是否存在一组关于命题变元的真值指派使A为真. 显然,如A为真,则CNF的每一个子句中必有一个命题变元为1(真). 2 遗传算法

遗传算法解决3SAT问题(C++实现代码)

1 SAT问题描述 命题逻辑中合取范式 (CNF) 的可满足性问题 (SAT)是当代理论计算机科学的核心问题, 是一典型的NP 完全问题.在定义可满足性问题SAT之前,先引进一些逻辑符号. 一个 SAT 问题是指: 对于给定的 CNF 是否存在一组关于命题变元的真值指派使A为真. 显然,如A为真,则CNF的每个子句中必有一个命题变元为1(真). 2 遗传算法 遗传算法类似于自然进化,通过作用于染色体上的基因寻找好的染色体来求解问题.与自然界相似,遗传算法对求解问题的本身一无所知,它所需要的仅是对

SA:利用SA算法解决TSP(数据是14个虚拟城市的横纵坐标)问题——Jason niu

%SA:利用SA算法解决TSP(数据是14个虚拟城市的横纵坐标)问题--Jason niu X = [16.4700 96.1000 16.4700 94.4400 20.0900 92.5400 22.3900 93.3700 25.2300 97.2400 22.0000 96.0500 20.4700 97.0200 17.2000 96.2900 16.3000 97.3800 14.0500 98.1200 16.5300 97.3800 21.5200 95.5900 19.4100

遗传算法解决0-1背包问题

1 import numpy 2 import matplotlib.pyplot as plt 3 4 5 data = numpy.array([[77, 92], 6 [22, 22], 7 [29, 87], 8 [50, 46], 9 [99, 90]]) 10 11 12 class GA(object): 13 """ 14 遗传算法解决0-1背包问题 15 """ 16 17 def __init__(self, length,