#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <sstream>
#include <climits>
#include <cmath>
#include <string>
#include <vector>
#include <algorithm>
#include <queue>
#include <map>
#include <functional>
#include <set>
#include <numeric>
#include <stack>
#include <utility>
#include <time.h>
#include <iterator>
#include <bitset>
#include <random>
//#include "util.h"

using namespace std;
typedef unsigned uint;
typedef long long lint;
typedef unsigned long long ulint;



//呪文
template <typename _KTy, typename _Ty> ostream& operator << (ostream& ostr, const pair<_KTy, _Ty>& m) { cout << "{" << m.first << ", " << m.second << "}"; return ostr; }
template <typename _KTy, typename _Ty> ostream& operator << (ostream& ostr, const map<_KTy, _Ty>& m) { if (m.empty()) { cout << "{ }"; return ostr; } cout << "{" << *m.begin(); for (auto itr = ++m.begin(); itr != m.end(); itr++) { cout << ", " << *itr; } cout << "}"; return ostr; }
template <typename _Ty> ostream& operator << (ostream& ostr, const vector<_Ty>& v) { if (v.empty()) { cout << "{ }"; return ostr; }	cout << "{" << v.front(); for (auto itr = ++v.begin(); itr != v.end(); itr++) { cout << ", " << *itr; }	cout << "}"; return ostr; }
template <typename _Ty> ostream& operator << (ostream& ostr, const set<_Ty>& s) { if (s.empty()) { cout << "{ }"; return ostr; } cout << "{" << *(s.begin()); for (auto itr = ++s.begin(); itr != s.end(); itr++) { cout << ", " << *itr; }	cout << "}"; return ostr; }
//template <typename T> void print(T* v, int N) { if (N == 0) cout << "{ }"; cout << "{" << v[0]; for (int i = 1; i < N; i++) cout << ", " << v[i]; cout << "}"; }
#define PI 3.14159265358979323846
#define EPS 1e-8
#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define REP(i,n)  FOR(i,0,n)
#define all(x) (x).begin(), (x).end()


class Dijkstra {

	const int INF;

	// d[i] : 始点 s から頂点 i への最短距離
	// d[i] = min(d[j] + (j から i への辺のコスト) | e = (j, i) in E)
	vector<int> d;
	vector<int> prev;

public:

	typedef pair<int, int> pii;

	// Dijkstra 法 O(|V|^2) (負の辺がない場合)
	// cost : 隣接行列, s : スタート地点
	// cost が存在しない場合は INF を入れておく
	Dijkstra(const vector<vector<int> >& cost, int s)
		: INF(1 << 29), d(cost.size(), INF), prev(cost.size(), -1)
	{
		int V = cost.size();
		vector<bool> used(V, false);

		d[s] = 0;
		while (true) {
			int v = -1;
			// まだ使われていない頂点のうち距離が最小のものを探す
			for (int u = 0; u < V; u++) {
				if (!used[u] && (v == -1 || d[u] < d[v])) v = u;
			}

			if (v == -1) break;

			used[v] = true;

			for (int u = 0; u < V; u++) {
				if (d[u] > d[v] + cost[v][u]) {
					d[u] = d[v] + cost[v][u];
					prev[u] = v;
				}
			}
		}
	}

	vector<int> shortest_path_cost() { return d; }
	int shortest_path_cost(int v) { return d[v]; }

	vector<int> get_path(int t) {
		vector<int> path;
		// t が s になるまで prev[t] を辿っていく
		for (; t != -1; t = prev[t]) path.push_back(t);
		reverse(all(path));
		return path;
	}

};

int ProblemD()
{
	int H, W;
	cin >> H >> W;
	int c[10][10] = {};
	for (int i = 0; i < 10; i++) {
		for (int j = 0; j < 10; j++) {
			cin >> c[i][j];
		}
	}

	int count[10] = {};
	for (int i = 0; i < H * W; i++) {
		int tmp;
		cin >> tmp;
		if(tmp != -1) count[tmp]++;
	}

	int V = 10;
	const int INF = 1 << 29;
	vector<vector<int> > cost(V, vector<int>(V, INF));
	for (int i = 0; i < 10; i++) {
		for (int j = 0; j < 10; j++) {
			cost[i][j] = c[i][j];
		}
	}
	
	int ans = 0;
	for (int i = 0; i < 10; i++) {
		if (i == 1) continue;
		ans += count[i] * Dijkstra(cost, i).shortest_path_cost(1);
	}

	cout << ans << endl;

	return 0;
}

int main()
{
	//clock_t start, end;
	//start = clock();

	ProblemD();
	
	//end = clock();
	//printf("%d msec.\n", end - start);

	return 0;
}

Measured memory_bytes: 256