旅行商问题模板
题意
旅行商问题,经过每个点一次,问从原点出发走回原点的最小距离
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; } /*样例区 */ //------------------------------------------------------------