//参考了挑战程序设计第二版的tsp,dp[S][v]表示在已经访问了集合S中的点情况下
//从出发访问剩下的节点并回到0号起点的最少花费dp[V][0]都是0,
//从0号节点回到0花费肯定是0,
//dp[S][v] = min(dp[S|{u}][u]+d[v][u],dp[S][v]){u不在当前的集合中}
//这样我们从[0,0]这个状态开始进行记忆化搜索,就一定能得到我们想要的答案
//对于递推的做法,目前还有一丝的疑惑
//书上说对于集合S(i)包含于S(j),就有i<=j;
//solve3()中dp[S][v]表示当前在v点,还需访问S中的城市各一次后回到0处的最小花费
//初始的时候dp[0][i]=d[i][0],其他都为无穷大,状态转移方程为
//dp[S][v] = min(dp[S][v],dp[S-{j}][j]+d[i][j])(j属于S)
//最后dp[S][0]就是我们要求的答案
//每种做法,各有千秋吧,仅以此题纪念自己开启TSP之旅~继续练吧
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <cfloat>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <functional>
#include <iostream>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <vector>
#define ceil(a,b) (((a)+(b)-1)/(b))
#define endl '\n'
#define gcd __gcd
#define highBit(x) (1ULL<<(63-__builtin_clzll(x)))
#define popCount __builtin_popcountll
typedef long long ll;
using namespace std;
const int MOD = 1000000007;
const long double PI = acos(-1.L);
template<class T> inline T lcm(const T& a, const T& b) { return a/gcd(a, b)*b; }
template<class T> inline T lowBit(const T& x) { return x&-x; }
template<class T> inline T maximize(T& a, const T& b) { return a=a<b?b:a; }
template<class T> inline T minimize(T& a, const T& b) { return a=a<b?a:b; }
const int maxn = 13;
int d[maxn][maxn];
int dp[1 << maxn][maxn];
int n;
const int inf = 0x3f3f3f3f;
void init(){
n++;
for (int i=0;i<n;i++)
for (int j=0;j<n;j++)
scanf("%d",&d[i][j]);
}
int dfs(int S,int v){
if (dp[S][v]>=0)
return dp[S][v];
if (S==(1<<n)-1&&v==0){
return dp[S][v]=0;
}
int res = inf;
for (int u=0;u<n;u++)
if (!((S>>u)&1)){
res = min(res,dfs(S|(1<<u),u)+d[v][u]);
}
return dp[S][v] = res;
}
void floyd(){
for (int k=0;k<n;k++)
for (int i=0;i<n;i++)
for (int j=0;j<n;j++)
if (d[i][j]>d[i][k]+d[k][j])
d[i][j] = d[i][k]+d[k][j];
}
void TSP(){
// for (int i=0;i<n;i++)
dp[(1<<n)-1][0]=0;
for (int S=(1<<n)-1;S>=0;S--)
for (int i=0;i<n;i++)
for(int u=0;u<n;u++)
if (!((S>>u)&1)){
dp[S][i] = min(dp[S][i],dp[S|(1<<u)][u]+d[i][u]);
}
}
void solve(){
memset(dp,-1,sizeof(dp));
printf("%d\n",dfs(0,0));
}
void solve2(){
memset(dp,inf,sizeof(dp));
TSP();
printf("%d\n",dp[0][0]);
}
void print(){
for (int i=0;i<(1<<n);i++){
for (int j=0;j<n;j++)
printf("%d ",dp[i][j]);
puts("");
}
}
void solve3(){
memset(dp,inf,sizeof(dp));
for (int i=0;i<n;i++)
dp[0][i] = d[i][0];
for (int S=0;S<(1<<n);S++)
for (int v=0;v<n;v++)
for (int u=0;u<n;u++)
if ((S>>u)&1)
dp[S][v] = min(dp[S][v],dp[S^(1<<u)][u]+d[v][u]);
//int res=inf;
// print();
// for (int i=0;i<n;i++)
// res = min(res,dp[i][0]);
printf("%d\n",dp[(1<<n)-1][0]);
}
int main() {
//freopen("G:\\Code\\1.txt","r",stdin);
while(scanf("%d",&n)!=EOF){
if (!n)
break;
init();
floyd();
//solve();
//solve2();
solve3();
}
return 0;
}
08-22
08-22
08-22
08-22