#include <iostream>
#include <sstream>
#include <string>
#include <queue>
#include <algorithm>
#include <cstdlib>
using namespace std;

#define FOR(a,b,c) for ( int a = b; a < (int)c; a++ )
#define REP(a,b) FOR(a,0,b)

class Pos {
public:
    int r, c;
    bool operator == ( const Pos& p ) const {
        return r == p.r && c == p.c;
    }
    bool operator < ( const Pos& p ) const {
        return r == p.r ? c < p.c : r < p.r;
    }
    Pos() { r=0, c=0; }
    Pos( int r_, int c_ ): r(r_), c(c_) {}
};

class Node {
public:
    int cost;
    int a;
    Pos p;
    Node() { cost = 0, a = 0, p = Pos(0,0); }
    Node( int cost_, int a_, int r, int c ) { cost = cost_, a = a_, p = Pos( r, c ); }
    bool operator == ( const Node& node ) const {
        return cost == node.cost;
    }
    bool operator < ( const Node& node ) const {
        return cost < node.cost;
    }
    bool operator > ( const Node& node ) const {
        return cost > node.cost;
    }
};

typedef priority_queue <Node, vector<Node>, greater<Node> > QUEUE;

// global var
const int size = 31;
int w, h;
int s[size][size];
int c[4];
int D[4][size][size]; // min cost

bool isValid( Pos p ) 
{
    return p.r >= 0 && p.r < h && p.c >= 0 && p.c < w;
}

// a%b
int getRem( int a, int b )
{
    int rem = a % b;
    if ( rem < 0 ) rem = b + rem;
    return rem;
}

int main( void )
{
    while ( cin >> w >> h && w && h ) {
        // init
        REP(i,size) REP(j,size) s[i][j]=0;
        REP(i,size) REP(j,size) REP(k,4) D[k][i][j]=1<<24;
        REP(i,4) c[i] = 0;

        // input
        for ( int i = 0; i < h; i++ ) {
            for ( int j = 0; j < w; j++ ) {
                cin >> s[i][j];
            }
        }
        for ( int i = 0; i < 4; i++ ) {
            cin >> c[i];
        }

        // proc
        int answer = 1<<24;
        QUEUE Q;
        Node start;
        Pos goal( h-1, w-1 );
        Q.push( start );
        D[0][start.p.r][start.p.c] = 0;

        while ( !Q.empty() ) {
            Node node = Q.top();
            Q.pop();

            if ( node.p == goal ) {
                answer = min( answer, D[node.a][node.p.r][node.p.c] );
                break;
            }
            // proc
            for ( int i = 0; i < 4; i++ ) {
                int cost = node.cost;
                int a = node.a;
                Pos p = node.p;
                Node next_node = node;

                // cost
                if ( i != s[p.r][p.c] ) {
                    cost += c[i];
                }

                // operation
                if ( i == 1 ) {
                    a = getRem( a+1, 4 );
                } else if ( i == 2 ) {
                    a = getRem( a+2, 4 );
                } else if ( i == 3 ) {
                    a = getRem( a-1, 4 );
                }

                // move
                if ( a == 0 ) {
                    p.c++;
                } else if ( a == 1 ) {
                    p.r++;
                } else if ( a == 2 ) {
                    p.c--;
                } else if ( a == 3 ) {
                    p.r--;
                }

                if ( !isValid( p ) ) {
                    continue;
                }

                if ( cost >= D[a][p.r][p.c] ) continue;
                D[a][p.r][p.c] = cost;
                next_node.cost = cost;
                next_node.a = a;
                next_node.p = p;
                Q.push( next_node );
            }
        }

        // output
        cout << answer << endl;
    }
    return 0;
}

Measured memory_bytes: 1024