(填坑)数学建模之旅行路线规划问题(状压+Dijkstra)

最近突然想起很久以前同学问的一道数模题,是道NPC问题,当时不会搞,现在发现用状压可以搞出来,所以就把这个坑填上了

《(填坑)数学建模之旅行路线规划问题(状压+Dijkstra)》

《(填坑)数学建模之旅行路线规划问题(状压+Dijkstra)》

设状态(S,u)表示已访问过的景点集合为S且当前在第u个景点,用求最短路的方式进行转移即可。

虽然题目说每个景点可以经过多次,但最优路线还是每个景点都只经过了一次,囧…

ps:原代码的Dijkstra算法有误,现已更正(spfa用惯了,Dijkstra都不会写了,唉)

更新日期2019.1.5

#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
const int INF=0x3f3f3f3f;
const int N=10;
int dis[N][N]= {
    {0,300,360,210,590,475,500,690},
    {300,0,380,270,230,285,200,390},
    {360,380,0,510,230,765,580,770},
    {210,270,510,0,470,265,450,640},
    {590,230,230,470,0,515,260,450},
    {475,285,765,265,515,0,460,650},
    {500,200,580,450,260,460,0,190},
    {690,390,760,640,450,650,190,0},
};
int d[1<<N][N],vis[1<<N][N];

struct node {
    int S,u;
    node(int S=0,int u=0):S(S),u(u) {}
    bool operator<(const node& b)const {
        return d[S][u]>d[b.S][b.u];
    }
};

node pre[1<<N][N];

void printans(int S,int u) {
    if(u!=0)printans(pre[S][u].S,pre[S][u].u);
    printf("%d ",u);
}

int Dij() {
    memset(d,INF,sizeof d);
    memset(vis,0,sizeof vis);
    priority_queue<node> q;
    q.push(node(1<<0,0));
    d[1<<0][0]=0;
    while(!q.empty()) {
        int S=q.top().S,u=q.top().u;
        q.pop();
        if(vis[S][u]||u==7)continue;
        vis[S][u]=1;
        for(int v=1; v<8; ++v) {
            int S2=S|(1<<v);
            if(d[S2][v]<=d[S][u]+dis[u][v])continue;
            d[S2][v]=d[S][u]+dis[u][v];
            pre[S2][v]=node(S,u);
            q.push(node(S2,v));
        }
    }
    return d[(1<<8)-1][7];
}

int main() {
    printf("%d\n",Dij());
    printans((1<<8)-1,7);
    return 0;
}

求得最短路为1820
路线为 0 3 5 1 2 4 6 7

    原文作者:旅游交通路线问题
    原文地址: https://blog.csdn.net/a54665sdgf/article/details/83960865
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞