1. 程式人生 > >(填坑)數學建模之旅行路線規劃問題(狀壓+Dijkstra)

(填坑)數學建模之旅行路線規劃問題(狀壓+Dijkstra)

最近突然想起很久以前同學問的一道數模題,是道NP問題,當時不會搞,現在發現用狀壓可以搞出來,所以就把這個坑填上了

雖然題目說每個景點可以經過多次,但最優路線還是每個景點都只經過了一次,囧...

#define FRER() freopen("i.txt","r",stdin);
#define FREW() freopen("o.txt","w",stdout);
#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;
    vis[1<<0][0]=1;
    while(!q.empty()) {
        int S=q.top().S,u=q.top().u;
        q.pop();
        if(u==7)continue;
        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);
            if(!vis[S2][v]) {
                vis[S2][v]=1;
                q.push(node(S2,v));
            }
        }
    }
    return d[(1<<8)-1][7];
}

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