#include <iostream>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <algorithm>
#include <numeric>
#include <functional>
#include <set>
#include <sstream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cctype>
#include <climits>
#include <fstream>
#include <bitset>
#include <time.h>
#include <assert.h>

#define LL long long
#define VI vector<int>
#define VVI vector<vector<int>>
#define VB vector<bool>
#define VL vector<long long>
#define FOR(i,a,b) for(int i= (a); i<((int)b); ++i)
#define RFOR(i,a) for(int i=(a); i >= 0; --i)
#define FOE(i,a) for(auto i : a)
#define ALL(c) (c).begin(), (c).end()
#define RALL(c) (c).rbegin(), (c).rend()
#define DUMP(x)  cerr << #x << " = " << (x) << endl;
#define SUM(x) std::accumulate(ALL(x), 0LL)
#define MIN(v) *std::min_element(v.begin(), v.end())
#define MAX(v) *std::max_element(v.begin(), v.end())
#define EXIST(v,x) (std::find(v.begin(), v.end(), x) != v.end())
#define BIT(n) (1LL<<(n))
#define UNIQUE(v) v.erase(unique(v.begin(), v.end()), v.end());
#define EPS 1e-14

const std::string YES = "YES";
const std::string Yes = "Yes";
const std::string NO = "NO";
const std::string No = "No";

using namespace std;

template <class T> int find_index(T x, const std::vector<T> &v) {
    auto it = std::find(v.begin(), v.end(), x);
    if (it != v.end()) { return (int)std::distance(v.begin(), it); }
    return -1;
}

template <class T> void print(T x) {
    std::cout << x << std::endl;
}
// 4近傍（右, 下, 左, 上）
const vector<int> dy = { 0, -1, 0, 1 };
const vector<int> dx = { 1, 0, -1, 0 };

struct Edge {
    unsigned int from, to;
    int cost;
    bool operator<(const Edge& edge) const {
        return this->cost < edge.cost;
    }
    bool operator>(const Edge& edge) const {
        return this->cost > edge.cost;
    }
};


class ShortestPath {
public:
    /**
     * start_nodeから他のすべてのnodeへの最短距離(到達できないnodeはINT_MAX)をもとめる
     * edgeに負の重みがある場合{}を返す
     * O(|V||E|)
     * @param start_node
     * @param node_size
     * @param edges
     * @return
     */
    vector<int> bellman_ford(int start_node, int node_size, vector<Edge> edges) {
        vector<int> dist_list(node_size, INT_MAX);
        dist_list[start_node] = 0;

        int i;
        for (i = 0; i < node_size; ++i) {
            bool update = false;
            for (auto e : edges) {
                unsigned int from = e.from, to = e.to;
                int cost = e.cost;
                if (dist_list.at(from) != INT_MAX && dist_list.at(to) > dist_list.at(from) + cost) {
                    dist_list.at(to) = dist_list.at(from) + cost;
                    update = true;
                }
            }
            if (!update) { break; }
        }
        if (i == node_size) {
            return{};
        }
        else {
            return dist_list;
        }
    }

    /**
     * startからすべての頂点への最小距離を求める O(|E| log |V|)
     * @param start
     * @param graph[node] = [(to1, cost1), (to2, cost2), ...]
     * @return
     */
    vector<int> dijkstra(int start, vector<vector<pair<int, int>>> graph) {
        unsigned long n = graph.size();
        priority_queue<pair<int, int>> que; //[(最短距離, node番号)]
        que.push({0, start});

        vector<int> prev_list(n, -1);
        vector<int> dist_list(n, INT_MAX);
        dist_list[start] = 0;

        while (!que.empty()) {
            int now_dist = que.top().first;
            int from = que.top().second;
            que.pop();

            if (dist_list[from] < now_dist) {
                continue;
            }
            for (pair<int, int> p : graph[from]) {
                int to = p.first;
                int dist = p.second;
                int new_dist = now_dist + dist;

                if (dist_list[to] > new_dist) {
                    prev_list[to] = from;
                    dist_list[to] = new_dist;
                    que.push({new_dist, to});
                }
            }
        }

        return prev_list;
    }


    /**
     * 全ノード間の最短距離をもとめる
     * O(|V|^3)
     * @param v[i][j]には辺e=(i,j)のコスト(辺が存在しない場合はINT_MAX)
     * @return
     */
    vector<vector<int>> warshall_floyd(vector<vector<int>> v) {
        unsigned long n = v.size();
        for (int i = 0; i < n; ++i) {
            v[i][i] = 0;
        }

        for (int m = 0; m < n; ++m) {
            for (int s = 0; s < n; ++s) {
                for (int e = 0; e < n; ++e) {
                    if (v[s][m] != INT_MAX && v[m][e] != INT_MAX) {
                        v[s][e] = min(v[s][e], v[s][m] + v[m][e]);
                    }
                }
            }
        }
        return v;
    }
};


int main(int argc, char *argv[]) {
    cin.tie(0);
    ios::sync_with_stdio(false);

    int H, W;
    cin >> H >> W;
    VVI memo(10, VI(10, 0));
    FOR(i, 0, 10) {
        FOR(j, 0, 10) {
            int s;
            cin >> s;
            memo[i][j] = s;
        }
    }

    ShortestPath s;
    VVI d = s.warshall_floyd(memo);

    LL ans = 0;
    FOR(i, 0, H) {
        FOR(j, 0, W) {
            int x;
            cin >> x;
            if (x != -1) {
                ans += d[x][1];
            }
        }
    }

    print(ans);
}


Measured memory_bytes: 256