/*
S表示已經走過的城市,1表示已經走過,0表示未走過(位標記集合)
首先對於原圖進行floyd,得到一個最短路的圖(16^3,綽綽有餘啊)
然後遍歷所有的集合
f[x][S]中,x表示完成S集合時,最後走到的是x,然後儲存的值就是到這樣的狀態需要的最小花費。
可能覺得奇怪,假如一開始進行floyd,那麼a->b就變成a->c->b,那麼在a已入的情況下加入b,那c不是可以直接加入的嗎?
不要慌,a->c->b,就是a—>c,c->b,這兩條不會被改變(就算被改變,繼續遞歸下去想吧),就不會丟掉c了。
方程:f[x][S]=min(f[x][S],f[k][S^(1<<(x-1))]+_map[k][x]){其中,k已經在S中}
最後不要忘了加_map[x][0],要回去的233
*/
#include <iostream>
#include <cstdio>
using namespace std;
int n;
int f[16][66000],_map[16][16];
int main()
{
cin>>n;
for(int i=0;i<=n;i++){
for(int j=0;j<=n;j++){
scanf("%d",&_map[i][j]);
}
}
//floyd
for(int k=0;k<=n;k++){
for(int i=0;i<=n;i++){
for(int j=0;j<=n;j++){
if(i!=j&&i!=k&&j!=k){
if(_map[i][k]+_map[k][j]<_map[i][j])
_map[i][j]=_map[i][k]+_map[k][j];
}
}
}
}
int Smax=(1<<n)-1;
for(int S=1;S<=Smax;S++){
for(int i=1;i<=n;i++){
if(S&(1<<(i-1))){
if( (S^(1<<(i-1))) ==0){
f[i][S]=_map[0][i];
}else{
f[i][S]=99999999;
for(int j=1;j<=n;j++){
if(S&(1<<(j-1)) && i!=j){
f[i][S]=min(f[i][S],f[j][S^(1<<(i-1))]+_map[j][i]);
}
}
}
}
}
}
int ans=99999999;
for(int i=1;i<=n;i++){
ans=min(ans,f[i][Smax]+_map[i][0]);
}
cout<<ans;
return 0;
}
covs 2800 送外賣
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.