旅行商问题模板

题意

旅行商问题,经过每个点一次,问从原点出发走回原点的最小距离

P对NP问题是Steve Cook于1971年首次提出。“P/NP问题”,这里的P指多项式时间(Polynomial),一个复杂问题如果能在多项式时间内解决,那么它便被称为P问题,这意味着计算机可以在有限时间内完成计算;NP指非确定性多项式时间(nondeterministic polynomial),一个复杂问题不能确定在多项式时间内解决,假如NP问题能找到算法使其在多项式时间内解决,也就是证得了P=NP。

旅行商问题由于每两个点都要走一次,所以是np问题。

输入

n,m代表节点数和边数。

m行输入a,b,c,代表a到b有一条边c (无向图)

 分析

记忆化搜索来写

f[st][i] 表示当前状态是st,从1号点出发最后到达的点是i点。

其中st = 111111 时表示所有点都走过,st=111101表示2号点没走过。

状态转移:f[st][i] = min(f[st][i], f[st'][x] + a[x][i]);   其中st' + 1 <<(x-1) == st 表示st 状态的前一步。

//-------------------------代码----------------------------

//#define int ll
const int N = 3000;
int n,m;
int a[N][N];
int f[N][N];

ll deal(int st,int x) {
    if(f[st][x] <= 1e10) {
        return f[st][x];
    }
    int st1 = st - (1 << (x - 1));
    fo(i,1,n) {
        if(a[i][x] == 0) continue;
        if(((st1 >> (i - 1)) & 1) == 1) {
            f[st][x] = min(f[st][x],deal(st1,i) + a[i][x])
        }
    }
    return f[st][x];
}

void solve()
{
    cin>>n>>m;
    fo(i,1,m) {
        int x,y,z;
        cin>>x>>y>>z;
        a[x][y] = z;
        a[y][x] = z;
    }
    ms(f,inf);
    f[1][1] = 0;
    int st = (1 << n) - 1;
    ll ans = inf;
    fo(i,2,n) {
        ll tmp = deal(st,i);
        if(a[i][1] != 0) ans = min(tmp+a[i][1],ans);
    }
    cout<<ans<<endl;
}

signed main(){
    AC();
    clapping();TLE;

//    int t;cin>>t;while(t -- )
    solve();
//    {solve(); }
    return 0;
}

/*样例区


*/

//------------------------------------------------------------

 

posted @ 2022-08-03 11:21  er007  阅读(84)  评论(0编辑  收藏  举报