遗传算法解决旅行商问题(附C++代码)

大连海事大学智能科学与技术专业课程设计福利

写法说明

该实验通过调整:生成地图的类型(1.随机边权抽象图。2.满足三角形不等式规则的实际二维平面地图),种群数量,迭代代数,变异概率等相关影响结果的因素,分别对随机生成的地图进行求解。并通过dfs暴力搜索对点数比较少的地图暴力求解最优解。经过比较发现,种群数量以及迭代次数都和求解所得路径的长度成负相关关系。

附代码:

#include<bits/stdc++.h>
using namespace std;
#define maxn 150
#define UNIT 2052
#define inf 0x3f3f3f3f
const double Pacs=0.8;//杂交概率
const double Pvan=0.05;//变异概率
struct way
{
    int q[maxn];
    double val;
}ans;
vector<way>a;
bool operator < (way a,way b)
{
    return a.val>b.val;
}
int n,m,T_T;///n为点数,m为个体数
double dis[maxn][maxn];
int make_data(int n,int kind)//生成n个点的无向边权完全图
{
    memset(dis,0,sizeof(dis));
    if(kind==1)//生成平面n点,满足三角形不等式
    {
        double x[maxn],y[maxn];
        for(int i=1;i<=n;i++)
        {
            x[i]=rand();
            y[i]=rand();
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=i;j<=n;j++)
            {
                double sx=x[i]-x[j],sy=y[i]-y[j];
                dis[j][i]=dis[i][j]=sqrt(sx*sx+sy*sy);
            }
        }
    }
    if(kind==2)//随机生成完全图
    {
        for(int i=1;i<=n;i++)
        {
            for(int j=i;j<=n;j++)
            {
                double sx=rand(),sy=rand();
                dis[j][i]=dis[i][j]=sqrt(sx*sx+sy*sy);
            }
        }
    }
    return n;
}
void outmap()
{
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            printf("%.5lf ",dis[i][j]);
        }
        printf("\n");
    }
}
void outway(way x)
{
    printf("%lf : ",x.val);
    for(int i=0;i<n;i++)
    {
        printf("%d -> ",x.q[i]);
    }
    printf("%d\n",x.q[0]);
}
double Get_val(way x)
{
    double ret=0;
    for(int i=0;i<n-1;i++)
    {
        ret+=dis[x.q[i]][x.q[i+1]];
    }
    ret+=dis[x.q[n-1]][x.q[0]];
    return ret;
}
int creat_way(int x)//随机生成x个路径
{
    a.clear();
    way now;
    int m=0;
    x--;
    for(int i=0;i<n;i++) now.q[i]=i+1;
    now.val=Get_val(now);
    a.push_back(now);
    ans=now;
    outway(ans);
    while(x--)
    {
        for(int i=0;i<n;i++)
        {
            now.q[i]=a[m].q[i];
        }
        m++;
        random_shuffle(now.q,now.q+n);
        now.val=Get_val(now);
        a.push_back(now);
        //outway(now);
        if(ans<now)ans=now;
    }
    return a.size();
}
void variation(way &x)
{
    int p1=rand()%n,p2=rand()%n;
    int temp=x.q[p1]; x.q[p1]=x.q[p2]; x.q[p2]=temp;
    x.val=Get_val(x);
}
way across(way a,way b)
{
    bool vis[maxn]={0};
    way ret;
    int p1=rand()%n,p2=rand()%n;
    int l=min(p1,p2),r=max(p1,p2),cnt=0;
    for(int i=l;i<=r;i++)
    {
        ret.q[cnt++]=a.q[i];
        vis[a.q[i]]=1;
    }
    for(int i=0;i<n;i++)
    {
        if(!vis[b.q[i]])
        {
            ret.q[cnt++]= b.q[i];
        }
    }
    //outway(ret);
    ret.val=Get_val(ret);
    return ret;
}
vector<way> work_Ga()//一次迭代
{
    double s[UNIT]={0};
    vector<way>ret;
    int e=a.size(),i,j;
    for(i=0;i<e;i++)
    {
        s[i+1]=s[i]+a[i].val;
    }
    for(i=0,j=e;i+1<e;i +=2)//杂交生成子代
    {
        if((rand()%1000) > Pacs*1000)continue;
        way temp=across(a[i],a[i+1]);
        if((rand()%1000) < Pvan*1000 )variation(temp);
        s[j+1]=s[j]+temp.val;
        j++;
        a.push_back(temp);
        if(ans<temp)
        {
            ans=temp;
            //outway(ans);
        }
    }
    double limit=s[a.size()-1];
    int aim_num=m;//下一代个数
    while(aim_num--)
    {
        double pos=limit+1;
        while(pos>limit)
        {
            pos=0.0001*(rand()%10000)+((long long int)rand()*rand())%((int)floor(limit)+1);
        }
        int l=0,r=a.size()-1;
        //printf("pos=%lf %d limit=%lf %d\n",pos,r,limit,(int)floor(limit));
        //for(int i=0;i<r;i++)printf("%lf ",s[i]);printf("\n\n\n");
        while(l<=r)
        {
            int mid=(l+r)/2;
            if(s[mid]>=pos)r=mid-1;
            else l=mid+1;
        }
        if(ans<a[r+1])
        {
            ans=a[r+1];
            //outway(ans);
        }
        ret.push_back(a[r+1]);
    }
    return ret;
}
bool test_vis[maxn];
way test_best;
void dfs(int x,way now)
{
    if(x==n)
    {
        now.val=Get_val(now);
        if(test_best<now)test_best=now;
        return;
    }
    for(int i=1;i<=n;i++)
    {
        if(!test_vis[i])
        {
            test_vis[i]=1;
            now.q[x]=i;
            dfs(x+1,now);
            test_vis[i]=0;
        }
    }
}
way BM_test()
{
    memset(test_vis,0,sizeof(test_vis));
    test_best.val=inf;
    way now;
    dfs(0,now);
    return test_best;
}
void OutInformation()
{
    printf("交叉概率:%.2lf\n变异概率: %.2lf\n完全图点数:%d\n种群个数: %d\n迭代次数: %d\n",
           Pacs,Pvan,n,m,T_T);
}
int main()
{
    srand(19980720);
    n=make_data(50,1);
    //outmap();
    printf("按顺序遍历结果:");
    m=creat_way(1000);
    //printf("暴力搜索最优结果:");outway( BM_test() );///暴力测试n个点的最优解
    T_T = 100;//迭代次数
    OutInformation();
    while(T_T--)
    {
        //printf("s");
        a=work_Ga();
        //if(T_T%10)outway(ans);
    }
    printf("遗传算法得到结果:");
    outway(ans);
    while(1)getchar();
    return 0;
}
全部评论

相关推荐

不愿透露姓名的神秘牛友
07-07 14:00
不想多说了,什么逆天HR,还要教我礼貌😂
机械打工仔:这不纯傻卵吗,他还操心上别人老板了
投递BOSS直聘等公司7个岗位
点赞 评论 收藏
分享
06-13 17:33
门头沟学院 Java
顺序不记了,大致顺序是这样的,有的相同知识点写分开了1.基本数据类型2.基本数据类型和包装类型的区别3.==和equals区别4.ArrayList与LinkedList区别5.hashmap底层原理,put操作时会发生什么6.说出几种树型数据结构7.B树和B+树区别8.jvm加载类机制9.线程池核心参数10.创建线程池的几种方式11.callable与runnable区别12.线程池怎么回收线程13.redis三剑客14.布隆过滤器原理,不要背八股,说说真正使用时遇到了问题没有(我说没有,不知道该怎么回答了)15.堆的内存结构16.自己在写项目时有没有遇见过oom,如何处理,不要背八股,根据真实经验,我说不会17.redis死锁怎么办,watchdog机制如何发现是否锁过期18.如何避免redis红锁19.一个表性别与年龄如何加索引20.自己的项目的QPS怎么测的,有没有真正遇到大数量表21.说一说泛型22.springboot自动装配原理23.springmvc与springboot区别24.aop使用过嘛?动态代理与静态代理区别25.spring循环依赖怎么解决26.你说用过es,es如何分片,怎么存的数据,1000万条数据怎么写入库中27.你说用limit,那么在数据量大之后,如何优化28.rabbitmq如何批次发送,批量读取,答了延迟队列和线程池,都不对29.计网知不知道smtp协议,不知道写了对不对,完全听懵了30.springcloud知道嘛?只是了解反问1.做什么的?短信服务,信息量能到千万级2.对我的建议,基础不错,但是不要只背八股,多去实际开发中理解。面试官人不错,虽然没露脸,但是中间会引导我回答问题,不会的也只是说对我要求没那么高。面完问我在济宁生活有没有困难,最快什么时候到,让人事给我聊薪资了。下午人事打电话,问我27届的会不会跑路,还在想办法如何使我不跑路,不想扣我薪资等。之后我再联系吧,还挺想去的😭,我真不跑路哥😢附一张河科大幽默大专图,科大就是大专罢了
查看30道真题和解析
点赞 评论 收藏
分享
怎么起名字:早知道就不读书了,害得我送外卖还得扶眼镜
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务