#include <iostream>
#include <vector>
#include <array>
#include <set>
#include <cmath>
#include <string>
#include <sstream>
#include <queue> 
#include <list>
#include <stack>
#include <unordered_map>
#include <algorithm> 
#include <numeric>  
#include <functional>
#include <cassert>
#include <bitset>
#include <cctype>  
#include <iomanip> 
#include <limits>  
#include <regex>
// std::numeric_limits<int>::max(), min()
// std::setprecision(X)
// std::islower(), std::isupper(), std::tolower, std::toupper
// std::accumulate(m.begin(), m.end(), 0LL);
// std::sort(begin(),end()) // 0, 1, 2, 3 ,4 (default, less);
// std::priority_queue<int, vector<int>, less<int>> que; // 4, 3, 2, 1 (defualt, less) : 
// if ( std::regex_match(S, std::regex("(dream|dreamer|erase|eraser)*")) ) std::cout << "YES" << std::endl;
 
#define rep(i, n) for(int i = 0; i < (int)(n);    i++)
#define sz(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()

template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return 1; } return 0; }
typedef long long ll;

ll gcd ( ll a, ll b ) { if ( b == 0 ) return a; else return gcd ( b, a%b ); }
ll lcm ( ll a, ll b ) { return a * b / gcd(a, b); }


class DIJKSTRA {
  typedef long long ll;

  private:
    std::vector<ll> from;
    std::vector<ll> cost;
    std::vector<std::unordered_map<ll, ll>> direction;
    ll start;
    bool directed;

  public:

    DIJKSTRA ( ll N , bool dir = false ) : directed(dir) {
      from.assign(N, std::numeric_limits<ll>::max());
      cost.assign(N, std::numeric_limits<ll>::max());
      direction.resize(N);
    }

    void push ( ll i, ll j, ll x ) {
      direction[i][j] = x;
      if ( !directed ) direction[j][i] = x;
    }

    void SetStart( ll i ) {
      start = i;
      cost[i] = 0;
      from[i] = i;
    }

    void Go () {
      std::priority_queue<std::pair<ll,ll>> pq;
      pq.push( {0, start} );
 
      while(!pq.empty()){
        auto cur = pq.top(); pq.pop();
        if ( cost[cur.second] < (cur.first * -1) ) continue;
        for(auto itr = direction[cur.second].begin(); itr != direction[cur.second].end(); ++itr) {
          if ( cost[itr->first] > cost[cur.second]+itr->second ) {
            cost[itr->first] = cost[cur.second]+itr->second;
            pq.push( { (cost[itr->first]*-1), itr->first } );
          }
        }
      }
      return;
    }

    ll get_cost ( ll i ){
      return cost[i];
    }

    std::string get_path ( ll i ) {
      std::string rtn = std::to_string(i) + " " ;
      ll cur = i;
      while( from[cur] != cur ) {
        rtn += std::to_string(from[cur]) + " ";
        cur = from[cur];
      }
      rtn += "(start)";
      return rtn;
    }
};


int main (void) {
  std::cin.tie(0);  std::ios::sync_with_stdio(false);
  int H, W; std::cin >> H >> W;
  std::vector<std::vector<int>> c(10, std::vector<int>(10));
  rep(i,10) rep(j,10) std::cin >> c[i][j];

  std::vector<int> A(10);
  rep(i,H) rep(j,W) {
    int a; std::cin >> a;
    if ( a == -1 ) continue;
    A[a]++;
  }

  ll ans = 0;
  for(int i=0; i<10; i++) {
    // i -> 1
    DIJKSTRA d(10, true);
    rep(m,10) rep(n,10) d.push(m,n,c[m][n]);
    d.SetStart(i);
    d.Go();
    ans += (A[i]*d.get_cost(1));
  }
  std::cout << ans << std::endl;

  return 0;
}


Measured memory_bytes: 256