#include<cstdio>
#define ll int
#define For(i,x,j) for(ll (i)=(x);(i)<=(j);++(i))
using namespace std;
inline ll rea(){
ll t=1,c=0;char x=getchar();
while(x<'0'||x>'9'){if(x=='-')t=-1;x=getchar();}
while(x>='0'&&x<='9'){c=c*10+x-'0';x=getchar();}
return t*c;
}
ll n,l;
struct df{
ll w,a[4];
}f[2010][4];//记录处理到第i个请求,由第j名服务员去完成,
ll road[210][210],ans;
int main(){
l=rea(),n=rea();
For(i,1,l)
For(j,1,l) road[i][j]=rea();
For(i,1,3){//初始化
f[0][i].a[1]=1;
f[0][i].a[2]=2;
f[0][i].a[3]=3;
f[0][i].w=0;
}
For(i,1,n){
ll x=rea();
For(j,1,3){
f[i][j].w=0x3f3f3f3f;
For(k,1,3){//枚举f[i-1][k],考虑从那种情况转移过来。
ll p=1,t=f[i-1][k].a[j];//如果其他服务员没有在x,则可以派j去
For(c,1,3) if(f[i-1][k].a[c]==x&&c!=j) p=0;
if(p&&f[i][j].w>f[i-1][k].w+road[t][x]){//更新派j去的最小值
f[i][j].w=f[i-1][k].w+road[t][x];
For(c,1,3) f[i][j].a[c]=f[i-1][k].a[c];//直接照搬数据
f[i][j].a[j]=x;
}
}
}
}
ans=min(min(f[n][1].w,f[n][2].w),f[n][3].w);//得到最小解
cout<<ans<<endl;
return 0;
}