#include <sstream>
#include <string>
#include <vector>
#include <map>
#include <algorithm>
#include <iostream>
#include <utility>
#include <set>
#include <cctype>
#include <queue>
#include <stack>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <climits>
using namespace std;
#define INF 100000000
#define MAXH 32
#define MAXW 32
typedef long long ll;

struct point {
    int x, y, dir;
};

struct edge {
    point from, to;
    int cost;
};

const int dx[4] = {1, 0, -1, 0};
const int dy[4] = {0, 1, 0, -1};

// 場所がh, wで方向が0~3の時のいろんな場所への遷移の仕方
// 0:右 1:上 2:左 3:下
vector<edge> es[MAXH][MAXW][4]; 

int s[MAXH][MAXW];
int w, h;
int c[4];
int dist[MAXH][MAXW][4];
bool used[MAXH][MAXW][4];

int main(void) {
    while (1) {
        // input
        cin >> w >> h;
        if (w == 0 && h == 0) break;
        for (int y = 0; y < h; y++) {
            for (int x = 0; x < w; x++) {
                cin >> s[y][x];
            }
        }
        for (int i = 0; i < 4; i++) {
            cin >> c[i];
        }

        // data arrange
        for (int y = 0; y < 32; y++) 
            for (int x = 0; x < 32; x++) 
                for (int i = 0; i < 4; i++)
                    es[y][x][i].clear();
        edge e;
        for (int y = 0; y < h; y++) {
            for (int x = 0; x < w; x++) {
                // straight
                for (int i = 0; i < 4; i++) {
                    int nx = x + dx[i];
                    int ny = y + dy[i];
                    if (0 <= nx && nx < w && 0 <= ny && ny < h) {
                        e.from.x = x; e.from.y = y; e.from.dir = i;
                        e.to.x = nx; e.to.y = ny; e.to.dir = i;
                        if (s[y][x] == 0) e.cost = 0;
                        else e.cost = c[0];
                        es[y][x][i].push_back(e);
                    }
                }
                // right
                for (int i = 0; i < 4; i++) {
                    int nx = x + dx[(i+1)%4];
                    int ny = y + dy[(i+1)%4];
                    if (0 <= nx && nx < w && 0 <= ny && ny < h) {
                        e.from.x = x; e.from.y = y; e.from.dir = i;
                        e.to.x = nx; e.to.y = ny; e.to.dir = (i+1) % 4;
                        if (s[y][x] == 1) e.cost = 0;
                        else e.cost = c[1];
                        es[y][x][i].push_back(e);
                    }
                }
                for (int i = 0; i < 4; i++) {
                    int nx = x - dx[i];
                    int ny = y - dy[i];
                    if (0 <= nx && nx < w && 0 <= ny && ny < h) {
                        e.from.x = x; e.from.y = y; e.from.dir = i;
                        e.to.x = nx; e.to.y = ny; e.to.dir = (i+2) % 4;
                        if (s[y][x] == 2) e.cost = 0;
                        else e.cost = c[2];
                        es[y][x][i].push_back(e);
                    }
                }
                for (int i = 0; i < 4; i++) {
                    int nx = x + dx[(i+3)%4];
                    int ny = y + dy[(i+3)%4];
                    if (0 <= nx && nx < w && 0 <= ny && ny < h) {
                        e.from.x = x; e.from.y = y; e.from.dir = i;
                        e.to.x = nx; e.to.y = ny; e.to.dir = (i+3) % 4;
                        if (s[y][x] == 3) e.cost = 0;
                        else e.cost = c[3];
                        es[y][x][i].push_back(e);
                    }
                }
            }
        }
        // data arrange check
        //for (int y = 0; y < h; y++) {
        //    for (int x = 0; x < w; x++) {
        //        for (int i = 0; i < 4; i++) {
        //            printf("(%d,%d,%d) check\n", x, y, i);
        //            for (int j = 0; j < es[y][x][i].size(); j++) {
        //                edge e = es[y][x][i][j];
        //                printf("(%d,%d,%d):%d \n", e.to.x, e.to.y, e.to.dir, e.cost);
        //            }
        //        }
        //    }
        //}
        
        // dijkstra
        for (int y = 0; y < h; y++) {
            for (int x = 0; x < w; x++) {
                for (int i = 0; i < 4; i++) {
                    dist[y][x][i] = INF;
                    used[y][x][i] = false;
                }
            }
        }
        dist[0][0][0] = 0;
        while (1) {
            int v = -1, u = -1, id = -1;
            for (int y = 0; y < h; y++) {
                for (int x = 0; x < w; x++) {
                    for (int i = 0; i < 4; i++) {
                        if (!used[y][x][i] && (v == -1 || dist[y][x][i] < dist[v][u][id])) {
                            v = y; u = x; id = i;
                        }
                    }
                }
            }
            if (v == -1) break;
            used[v][u][id] = true;
            for (int i = 0; i < es[v][u][id].size(); i++) {
                edge e = es[v][u][id][i];
                dist[e.to.y][e.to.x][e.to.dir] = min(dist[v][u][id] + e.cost, dist[e.to.y][e.to.x][e.to.dir]);
            }
        }
        int ans = INF;
        for (int i = 0; i < 4; i++) {
            ans = min(dist[h-1][w-1][i], ans);
        }
        cout << ans << endl;
    }
    return 0;
}

Measured memory_bytes: 1784