用遗传算法解决TSP问题
浅谈遗传算法:https://www.cnblogs.com/AKMer/p/9479890.html
Description
\(小m\)在踏上寻找\(小o\)的路程之后不小心碰到了大魔王\(fater\)。
大魔王看了看\(小m\)的命运,心生怜悯,便给\(小m\)和自己做一个交换的机会。
这个交换是这样的:
由于\(小o\)不知在天涯海角,\(小m\)的要找到实在是太难了。所以大魔王愿意把\(小m\)和\(小o\)同时扔到一个迷宫(\(n\)个点的完全无向图)里,但是\(小o\)在哪个点上是未知的。
\(小m\)初始在\(1\)号点。\(1\)号点上有迷宫出口,打开出口需要遍历整张图拿到全部点上的钥匙。\(小m\)要将自己日思夜念的\(小o\)从迷宫深处的不知方位的点带出来就必须遍历所有的点。然而大魔王并不愿意一昧的帮助\(小m\),他说如果\(小m\)重复经过一个点(\(1\)号点除外)或者走过的路程不是最短的环那么他和\(小o\)将永远无法逃出迷宫。
\(小m\)想见\(小o\),不管三七二十一便答应了大魔王。在进去之前大魔王给了他一张地图,然后便将\(小m\)扔进了迷宫并且关上了入口。
\(小m\)在黑暗的迷宫里才明白过来,自己虽然是\(OIer\),但是自己的\(Computer\)似乎被大魔王没收了。于是乎,作为同是\(OIer\)的挚友,他打电话告诉你这件事情并且希望你能帮助他。他将地图以一个矩阵的形式给了你。由于他实在是太想念\(小o\)了,但他也不好意思太麻烦你,所以他希望你能在\(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\)的数据
首先题目意思是要你求一个无向完全图中最短哈密尔顿环的长度。
对于这题用遗传算法,估价函数可以设成一个最长环长度减去当前染色体所表示的环的长度,那么环长度越短,适应性就会越高。
然后交换操作要进行一些改进。因为直接交换会使得某个染色体中重复出现某个点(会导致\(小m\)和\(小o\)不能逃出迷宫!!)。于是乎我们就将串与串之间交换改成在一条染色体上交换两个位置,和变异一起做了。
就大功告成了。如果是提答题的话遗传代数和变异次数可以设置多一点,如果是想在传统题上骗分记得不要设置太高导致\(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;//擦汗r存当前种群,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');//她叫小o,我是小m
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;
}
用遗传算法解决TSP问题的更多相关文章
- 转:遗传算法解决TSP问题
1.编码 这篇文章中遗传算法对TSP问题的解空间编码是十进制编码.如果有十个城市,编码可以如下: 0 1 2 3 4 5 6 7 8 9 这条编码代表着一条路径,先经过0,再经过1,依次下去. 2.选 ...
- 遗传算法解决TSP问题实现以及与最小生成树的对比
摘要: 本实验采用遗传算法实现了旅行商问题的模拟求解,并在同等规模问题上用最小生成树算法做了一定的对比工作.遗传算法在计算时间和占用内存上,都远远优于最小生成树算法. 程序采用Microsoft vi ...
- 遗传算法解决TSP问题
1实验环境 实验环境:CPU i5-2450M@2.50GHz,内存6G,windows7 64位操作系统 实现语言:java (JDK1.8) 实验数据:TSPLIB,TSP采样实例库中的att48 ...
- tsp问题——遗传算法解决
TSP问题最简单的求解方法是枚举法. 它的解是多维的.多局部极值的.趋于无穷大的复杂解的空间.搜索空间是n个点的全部排列的集合.大小为(n-1)! .能够形象地把解空间看成是一个无穷大的丘陵地带,各山 ...
- 遗传算法解决寻路问题——Python描述
概要 我的上一篇写遗传算法解决排序问题,当中思想借鉴了遗传算法解决TSP问题,本质上可以认为这是一类问题,就是这样认为:寻找到一个序列X,使F(X)最大. 详解介绍 排序问题:寻找一个序列,使得这个序 ...
- 遗传算法解决旅行商问题(TSP)
这次的文章是以一份报告的形式贴上来,代码只是简单实现,难免有漏洞,比如循环输入的控制条件,说是要求输入1,只要输入非0就行.希望会帮到以后的同学(*^-^*) 一.问题描述 旅行商问题(Traveli ...
- 基础遗传算法的TSP问题
一.简介 旅行商问题是一个经典的组合优化问题.一个经典的旅行商问题可以描述为:一个商品推销员要去若干个城市推销商品,该推销员从一个城市出发,需要经过所有城市后,回到出发地.应如何选择行进路线,以使总的 ...
- C++实现禁忌搜索解决TSP问题
C++实现禁忌搜索解决TSP问题 使用的搜索方法是Tabu Search(禁忌搜索) 程序设计 1) 文件读入坐标点计算距离矩阵/读入距离矩阵 for(int i = 0; i < CityNu ...
- 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 2 ...
随机推荐
- A/B(逆元)
A/B Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submiss ...
- intellij idea pycharm phpstorm webstorm 使用 FiraCode 作为编程字体,更新后字符乱码问题解决
先说使用下载 传送门 https://pan.baidu.com/s/1OI-novVYy-C74HIUfr9E6w windows: 1.下载后打开ttf文件夹,选择所有右键安装. 2.或者使用ch ...
- EasyPlayer RTSP播放器OCX RegSvr32注册报错,DllRegisterServer调用失败,错误代码为0x80040200 解决方法
问题描述 模块"EasyPlayer-RTSPWebActiveX.ocx" 已加载,但对DLLRegisterServer调用失败,错误代码为0x80040200. 解决方法 是 ...
- 九度OJ 1194:八进制 (进制转换)
时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:3521 解决:2058 题目描述: 输入一个整数,将其转换成八进制数输出. 输入: 输入包括一个整数N(0<=N<=100000 ...
- LLVM编译器
LLVM 1. 说说 LLVM(Low Level Virtual Machine)到底是什么吧 先说编译器:编译器是把程序员的代码翻译成机器可以理解的语言的工具: 再谈 LLVM:一个模块化和可重用 ...
- greenlet和gevent模块的区别?
协程是一中多任务实现方式,它不需要多个进程或线程就可以实现多任务. yield能实现协程,不过实现过程不易于理解,greenlet是在这方面做了改进,通过switch. greenlet可以实现协程, ...
- 我的Android进阶之旅------>Android疯狂连连看游戏的实现之实现游戏逻辑(五)
在上一篇<我的Android进阶之旅------>Android疯狂连连看游戏的实现之加载界面图片和实现游戏Activity(四)>中提到的两个类: GameConf:负责管理游戏的 ...
- 003-unity3d 物理引擎简介以及示例
一.概述 物理引擎就是模拟真实世界中物体碰撞.跌落等反应的引擎,通过ballence.愤怒的小鸟等理解.Unity3D的物理引擎使用的是Nvidia的PhysX. 物理引擎是一个计算机程序模拟牛顿力学 ...
- C#使用SQL语句时候的万用密码问题
实际上万用密码就是因为SQL里面的语句--是注释,利用bug添加用户名和密码. 例如,用户名为 adada’ or 1=1-- 第一个种写法登录成功了 第二种写法登录失败(正确) 第三种写法登录失败( ...
- python基础3 ---python数据类型二
ython基础 一.python数据类型 ------列表(list) 1.定义:[]内以逗号分隔,按照索引,存放各种数据类型,每个位置代表一个元素 特性:可存放多个不同类型的值:可修改指定索 ...