#include<stdio.h> #include<string.h> #include<ctype.h> #include<math.h> #include<iostream> #include<string> #include<set> #include<map> #include<vector> #include<queue> #include<bitset> #include<algorithm> #include<time.h> using namespace std; void fre(){freopen("c://test//input.in","r",stdin);freopen("c://test//output.out","w",stdout);} #define MS(x,y) memset(x,y,sizeof(x)) #define MC(x,y) memcpy(x,y,sizeof(x)) #define MP(x,y) make_pair(x,y) #define ls o<<1 #define rs o<<1|1 typedef long long LL; typedef unsigned long long UL; typedef unsigned int UI; template <class T1,class T2>inline void gmax(T1 &a,T2 b){if(b>a)a=b;} template <class T1,class T2>inline void gmin(T1 &a,T2 b){if(b<a)a=b;} const int N=0,M=0,Z=1e9+7,ms63=1061109567; int casenum,casei; int n; int a[30][30]; bool e[30]; int b[8]; int main() { while(scanf("%d",&n),n) { for(int i=0;i<n;i++) { for(int j=0;j<n;j++)scanf("%d",&a[i][j]); } MS(e,0); int m,x; scanf("%d",&m); for(int i=0;i<m;i++)scanf("%d",&x),e[x]=1; int g=0;b[0]=0; for(int i=0;i<30;i++)if(e[i])b[++g]=i; int ans=1e9; do { int tmp=0; for(int i=1;i<=g;i++)tmp+=a[b[i-1]][b[i]]; gmin(ans,tmp); }while(next_permutation(b+1,b+g+1)); printf("%d\n",ans); } return 0; } /* 【trick&&吐槽】 keep it simple and stupid 【题意】 有n(30)个站点0base。 我们一次拉n(7)个人,我们设计路线,只经过这n个人的目的地中的点,把这n个人用最短的路程全部送到。 输出最短路程。 【类型】 旅行商问题 状压DP 【分析】 这题一看就是典型的旅行商问题。 枚举状态,枚举上一次遍历的点,枚举接下来遍历的点,然后做转移。 然而数据这么小,直接阶乘搞吧!n!直接AC拉! 【时间复杂度&&优化】 O(目的地数量!) */