#include <iostream>
#include <vector>
#include <limits>
#include <algorithm>
#include <queue>
#include <utility>


int const N = 30;
int const Ord = 4;
int const inf = std::numeric_limits<int>::max() - 500000;

int const x_diff[] = {1, 0, -1, 0};
int const y_diff[] = {0, 1, 0, -1};


class robot
{
public:
    robot( int x, int y, int dir )
        : x_(x)
        , y_(y)
        , dir_(dir)
    {}

    bool operator<(robot const&) const{ return true; }

public:
    void forward()
    {
        x_ += x_diff[dir_];
        y_ += y_diff[dir_];
    }

    bool right_forward()
    {
        turn_right(); 
        forward();
    }

    void back()
    {
        turn_right(); turn_right(); 
        forward();
    }

    bool left_forward()
    {
        turn_left(); 
        forward();
    }                       


    int x() const { return x_; }
    int y() const { return y_; }
    int dir() const { return dir_; }

private:
    void turn_right()
    {
        ++dir_;
        if ( dir_ > 3 )
            dir_ = 0;
    }

    void turn_left()
    {
        --dir_;
        if ( dir_ < 0 )
            dir_ = 3;
    }

private:
    int x_, y_, dir_;
};



robot forward( robot const& r )
{
    robot d(r);
    d.forward();

    return d;
}

robot right_forward( robot const& r )
{
    robot d(r);
    d.right_forward();

    return d;
}

robot back( robot const& r )
{
    robot d(r);
    d.back();

    return d;
}

robot left_forward( robot const& r )
{
    robot d(r);
    d.left_forward();

    return d;
}

robot do_action( robot const& r, int const id )
{
    switch( id )
    {
    case 0:
        return forward( r );
    case 1:
        return right_forward( r );
    case 2:
        return back( r );
    case 3:
        return left_forward( r );
    }

    return r;
}




int main()
{
    using namespace std;

    for(;;)   
    {
        int table[N][N]; //x ,y
        int c[Ord];

        int w, h;
        cin >> w >> h;

        if ( w == 0 && h == 0 )
            break;

        for( int i=0; i<h; ++i )
            for( int j=0; j<w; ++j )
                cin >> table[j][i]; // set [x, y]

        for( int i=0; i<Ord; ++i ) {
            cin >> c[i];
        }

        int const g_x = w - 1;
        int const g_y = h - 1;

 
        int cost[N][N][Ord]; // x, y ,dir
        fill( &cost[0][0][0], &cost[0][0][0]+N*N*Ord, inf );

        robot const base_r( 0, 0, 0 );
        cost[base_r.x()][base_r.y()][base_r.dir()] = 0;

        typedef std::pair<int, robot> data_set;
        priority_queue<data_set, vector<data_set>, greater<data_set> > q;
        q.push( make_pair( 0, base_r ) );
        
        for(;;) {
            robot const r = q.top().second;
            int const r_cost = q.top().first;
            
            if ( r.x() == g_x && r.y() == g_y )
                break;

            q.pop();
  
            int per_cost[Ord];
            per_cost[0] = c[0];       // Forward
            per_cost[1] = c[1];       // Right
            per_cost[2] = c[2];       // Back
            per_cost[3] = c[3];       // Left

            int const action = table[r.x()][r.y()]; 
            if ( action != 4 ) {
                per_cost[action] = 0;
            }
            


            for( int act_id=0; act_id<Ord; ++act_id ) {
                robot const d = do_action( r, act_id );

                if ( d.x() < 0 || d.y() < 0 || d.x() >= w || d.y() >= h )
                    continue;

                if ( cost[d.x()][d.y()][d.dir()] > r_cost + per_cost[act_id] ) {
                    cost[d.x()][d.y()][d.dir()] = r_cost + per_cost[act_id];
                    q.push( make_pair( cost[d.x()][d.y()][d.dir()], d ) );
                }
            }
        }


        cout << q.top().first << endl;
    }
}

Measured memory_bytes: 1332