Problem:
Problem D:
Twirling Robot
Let's play a game using a robot on a rectangular board 
covered with a square mesh (Figure D-1).
The robot is initially set at the start square in the northwest corner
facing the east direction.
The goal of this game is to lead the robot
to the goal square in the southeast corner.
Figure D-1: Example of a board
The robot can execute the following five types of commands.
"Straight":
Keep the current direction of the robot, and move forward to the next square.
"Right":
Turn right with 90 degrees from the current direction, and move forward to the next square.
"Back":
Turn to the reverse direction, and move forward to the next square.
"Left":
Turn left with 90 degrees from the current direction, and move forward to the next square.
"Halt":
Stop at the current square to finish the game.
Each square has one of these commands assigned as shown in Figure D-2.
The robot executes the command assigned to the square where it resides,
unless the player gives another command to be executed instead.
Each time the player gives an explicit command, 
the player has to pay the cost that depends on the command type.
Figure D-2: Example of commands assigned to squares
The robot can visit the same square several times during a game.
The player loses the game when the robot goes out of the board
or it executes a "Halt" command before arriving at the goal square.
Your task is to write a program that calculates the minimum cost to lead the robot
from the start square to the goal one.
Input
The input is a sequence of datasets. 
The end of the input is indicated by a line containing two zeros separated by a space.
Each dataset is formatted as follows.
w h
s
(1,1)  ...
s
(1,
w
)
s
(2,1)  ...
s
(2,
w
)
...
s
(
h
,1)  ...
s
(
h
,
w
)
c
0
c
1
c
2
c
3
The integers
h
and
w
are the numbers of rows and columns of the board, 
respectively.
You may assume 2 ≤
h
≤ 30 and 2 ≤
w
≤ 30. 
Each of the following
h
lines consists of
w
numbers delimited by a space.
The number
s
(
i
,
j
) represents the command assigned to the square 
in the
i
-th row and the
j
-th column as follows.
0: "Straight"
1: "Right"
2: "Back"
3: "Left"
4: "Halt"
You can assume that a "Halt" command is assigned to the goal square.
Note that "Halt" commands may be assigned to other squares, too.
The last line of a dataset contains four integers
c
0
,
c
1
,
c
2
, and
c
3
, delimited by a space,  
indicating the costs that the player has to pay 
when the player gives
"Straight", "Right", "Back", and "Left" commands
respectively.
The player cannot give "Halt" commands.
You can assume that all the values of
c
0
,
c
1
,
c
2
, and
c
3
are between 1 and 9, inclusive.
Output
For each dataset, print a line only having a decimal integer indicating the minimum cost 
required to lead the robot to the goal.
No other characters should be on the output line.
Sample Input
8 3
0 0 0 0 0 0 0 1
2 3 0 1 4 0 0 1
3 3 0 0 0 0 0 4
9 9 1 9
4 4
3 3 4 0
1 2 4 4
1 1 1 0
0 2 4 4
8 7 2 1
2 8
2 2
4 1
0 4
1 3
1 0
2 1
0 3
1 4
...(truncated)

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
using namespace std;

using VS = vector<string>;    using LL = long long;
using VI = vector<int>;       using VVI = vector<VI>;
using PII = pair<int, int>;   using PLL = pair<LL, LL>;
using VL = vector<LL>;        using VVL = vector<VL>;

#define ALL(a)  begin((a)),end((a))
#define RALL(a) (a).rbegin(), (a).rend()
#define SZ(a) int((a).size())
#define SORT(c) sort(ALL((c)))
#define RSORT(c) sort(RALL((c)))
#define UNIQ(c) (c).erase(unique(ALL((c))), end((c)))
#define FOR(i, s, e) for (int(i) = (s); (i) < (e); (i)++)
#define FORR(i, s, e) for (int(i) = (s); (i) > (e); (i)--)
#define debug(x) cerr << #x << ": " << x << endl
const int INF = 1e9;                          const LL LINF = 1e16;
const LL MOD = 1000000007;                    const double PI = acos(-1.0);

/* -----  2018/06/12  Problem: AOJ 1156 / Link: http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=1156  ----- */
/* ------問題------

ロボットを使ったゲームをしよう． ロボットが 1 台，マス目状に区切られた長方形の盤面上に置かれている（図 D-1）． ロボットは，最初北西隅にあるスタート地点のマスに東方向を向いて配置されている． ゲームの目的は，ロボットを南東隅にあるゴールのマスまで誘導することである．
ロボットは，次の 5 種類の命令を実行することができる．
「直進 (Straight)」:
現在の進行方向のまま，次のマスに前進する．
「右折 (Right)」:
進行方向を 90 度右に変えて，次のマスに前進する．
「反転 (Back)」:
進行方向を 180 度変えて，次のマスに前進する．
「左折 (Left)」:
進行方向を 90 度左に変えて，次のマスに前進する．
「停止 (Halt)」:
現在のマスで止まって，ゲームを終了する．
各マスには，上述の命令のいずれかが割り当てられている（例：図 D-2）． 代わりに実行すべき別の命令をプレイヤーが与えない限り， ロボットは，現在いるマスの命令を実行する． プレイヤーが明示的に命令を与える際は，その都度， 命令の種類に応じたコストを支払う必要がある．
ロボットは，同じ場所を何度も訪れることが許されている． 一方で，ロボットが盤面外に前進するような命令を実行した場合や， ゴールに着く前に停止命令を実行した場合は，失格となる．
あなたの仕事は， ロボットをスタート地点からゴール地点に誘導するために必要な最小コストを求めるプログラムを書くことである．

-----問題ここまで----- */
/* -----解説等-----

前どこから来たかをもって、やる

----解説ここまで---- */

bool is_in(int x, int y, int h, int w) {
	return (0 <= x && x < w && 0 <= y && y < h);
}
int nxtstep(int cmd,int dir) {
	if (cmd == 0)return dir;
	if (cmd == 1)return (dir+1)%4;
	if (cmd == 2)return (dir+2)%4;
	if (cmd == 3)return (dir+3)%4;
	assert(0);
}
int main() {
	cin.tie(0);
	ios_base::sync_with_stdio(false);

	int W, H;
	int DY[8] = { 0, 1, 0, -1 };
	int DX[8] = { 1, 0, -1, 0 };

	while (cin >> W >> H, W) {
		VVI masu(H, VI(W));
		FOR(i, 0, H) {
			FOR(j, 0, W) {
				cin >> masu[i][j];
			}
		}
		VI co(4);
		FOR(i, 0, 4) {
			cin >> co[i];
		} // straight,ri,rev,le
		vector<VVI>dist(H, VVI(W, VI(4, INF)));
		using tp = tuple<int, int, int, int>;
		priority_queue<tp, vector<tp>, greater<tp>>q;
		dist[0][0][0] = 0;
		q.push(tp(0, 0, 0, 0));
		while (!q.empty()) {
			int x, y, cost, dir, nxdir;
			tie(cost, y, x, dir) = q.top(); q.pop();
			nxdir = dir;
			if (dist[y][x][dir] < cost)continue;
			int command = masu[y][x];

			if (command >= 0 && command <= 3) {
				nxdir = nxtstep(command, dir);
				int ny = y + DY[nxdir];
				int nx = x + DX[nxdir];
				if (is_in(nx, ny, H, W)) {
					if (dist[ny][nx][nxdir] > cost) {
						dist[ny][nx][nxdir] = cost;
						q.push(tp(cost, ny, nx, nxdir));
					}
				}
			}
			// change
			FOR(i, 0, 4) {
				nxdir = nxtstep(i, dir);
				int ny = y + DY[nxdir];
				int nx = x + DX[nxdir];
				if (is_in(nx, ny, H, W)) {
					if (dist[ny][nx][nxdir] > cost + co[i]) {
						dist[ny][nx][nxdir] = cost + co[i];
						q.push(tp(dist[ny][nx][nxdir], ny, nx, nxdir));

					}
				}
			}
		}
		int ans = INF;
		FOR(i, 0, 4) {
			ans = min(ans, dist[H - 1][W - 1][i]);
		}
		cout << ans << "\n";
	}

	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3588
final_rank: 8

code_snippet: #include <queue>
#pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")

// #ifndef ONLINE_JUDGE
// #define _GLIBCXX_DEBUG // 配列外参照のエラー
// #endif

// スタンダードライブラリ
#include <bits/stdc++.h>
using namespace std;

// 型関連
using ll = long long;
using lint = long long;
using pll = pair<ll, ll>;
using plll = tuple<ll, ll, ll>;
using pii = pair<int, int>;
using piii = tuple<ll, ll, ll>;
using vi = vector<int>;
using vvi = vector<vector<int>>;
using vvvi = vector<vector<vector<int>>>;
using vvvvi = vector<vector<vector<vector<int>>>>;
using vl = vector<ll>;
using vvl = vector<vector<ll>>;
using vvvl = vector<vector<vector<ll>>>;
using vvvvl = vector<vector<vector<vector<ll>>>>;

template <class T> using prique = priority_queue<T>;

// 型定数
constexpr ll mod = 998244353;
constexpr ll MOD = 1000000007;
int INF32 = 2e9;
ll INF64 = 9e18;
#define endl '\n';

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

/////////////////////////// print関連
template <typename T> void print(vector<T> A);
void print();
template <class Head, class... Tail> void print(Head &&head, Tail &&...tail);
void print(string S);
template <typename T> void print(vector<vector<T>> &F);

inline void Yes(bool f);

using piiii = tuple<int,int,int,int>;

///////////////////ここから//////////////////////
bool solve() {
    
    int W, H;
    cin >> W >> H;
    if (H == 0) {
        return false;
    }
    vvi S(H, vi(W));
    for (int i = 0; i < H; i++) {
        for (int j = 0; j < W; j++) {
            cin>>S[i][j];
        }
    }
    vi C(4);
    for (int i = 0; i < 4; i++) {
        cin>>C[i];
    }


    int dn[4] = {0, 3, 2, 1};
    vvvi dist(H, vvi(W, vi(4, INF32)));
    vvvi f(H, vvi(W, vi(4, 0)));
    priority_queue<piiii, vector<piiii>, greater<piiii>> que;
    que.emplace(0, 0, 0, 1);
    dist[0][0][1] = 0;
    while (!que.empty()) {
        auto [dis, i, j, d] = que.top();
        que.pop();
        if (f[i][j][d]) {
            continue;
        }
        f[i][j][d] = true;
        for (int n = 0; n < 4; n++) {
            int cost=0;
            if (S[i][j] != n) {
                cost+=C[n];
            }
            int nd = (d + dn[n]) % 4;
            int ni = i + dx[nd], nj = j + dy[nd];
            if (ni < 0 || ni >= H || nj < 0 || nj >= W) {
                continue;
            }
            if (dist[ni][nj][nd] > dis + cost) {
                dist[ni][nj][nd] = dis + cost;
                que.emplace(dis+cost,ni,nj,nd);
            }
        }
    }
    print(*min_element(dist[H - 1][W - 1].begin(), dist[H - 1][W - 1].end()));
    
    



    return true;
}


int main() {
    ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    while (solve());
}

////////////////////print/////////////////////////
// 1次元ベクトルを出力する
template <typename T> void print(vector<T> A) {
    if (A.size() == 0) {
        return;
    }
    for (size_t i = 0; i < A.size() - 1; i++) {
        cout << A[i] << ' ';
    }
    cout << A[A.size() - 1] << endl;
    return;
}

// 2次元ベクトルを出力する
template <typename T> void print(vector<vector<T>> &F) {
    for (size_t i = 0; i < F.size(); i++) {
        for (size_t j = 0; j < F[i].size(); j++) {
            cout << F[i][j];
            if (j < F[i].size() - 1) {
                cout << ' ';
            }
        }
        cout << endl;
    }
}

// 空白行を出力するprint
void print() { cout << endl; }

// 数値・文字列を空白区切りで出力する. print(a,b)など
template <class Head, class... Tail> void print(Head &&head, Tail &&...tail) {
    cout << head;
    if (sizeof...(tail) != 0)
        cout << " ";
    print(forward<Tail>(tail)...);
}

void print(string S) { cout << S << endl; }

//////////////出力関連

inline void Yes(bool f) {
    if (f) {
        cout << "Yes" << endl;
    } else {
        cout << "No" << endl;
    }
}
accuracy: 1
time_ms: 10
memory_kb: 3840
final_rank: 14

code_snippet: #include <bits/stdc++.h>
using namespace std;

bool solve() {
    int H, W;
    cin >> W >> H;
    if (H == 0 && W == 0) return false;
    vector<vector<int>> S(H, vector<int>(W));
    for (int i = 0; i < H; i++) {
        for (int j = 0; j < W; j++) cin >> S[i][j];
    }
    vector<int> C(4);
    for (int i = 0; i < 4; i++) cin >> C[i];
    int D[5] = {0, 1, 0, -1, 0};
    vector<vector<vector<int>>> cost(H, vector<vector<int>>(W, vector<int>(4, 1 << 30)));
    cost[0][0][0] = 0;
    // (cost, r, c, dir)
    priority_queue<tuple<int, int, int, int>, vector<tuple<int, int, int, int>>, greater<tuple<int, int, int, int>>> q;
    q.emplace(0, 0, 0, 0);
    while (q.size()) {
        auto [ct, r, c, d] = q.top();
        q.pop();
        if (cost[r][c][d] < ct) continue;
        for (int i = 0; i < 4; i++) {
            int nd = (d + i) % 4;
            int nr = r + D[nd], nc = c + D[nd + 1];
            if (0 <= nr && nr < H && 0 <= nc && nc < W) {
                if (cost[nr][nc][nd] > ct + C[i] * (i != S[r][c])) {
                    cost[nr][nc][nd] = ct + C[i] * (i != S[r][c]);
                    q.emplace(cost[nr][nc][nd], nr, nc, nd);
                }
            }
        }
    }
    cout << *min_element(cost[H - 1][W - 1].begin(), cost[H - 1][W - 1].end()) << endl;
    return true;
}

int main() {
    while (solve()) {}
}
accuracy: 1
time_ms: 10
memory_kb: 3712
final_rank: 10

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;

const int INF = 2e9;
int dx[]      = {0, 1, 0, -1};
int dy[]      = {1, 0, -1, 0};

void solve(int w, int h, vector<vector<int>> grid, vector<int> c) {
    priority_queue<tuple<int, int, int, int>, vector<tuple<int, int, int, int>>, greater<>> pq;
    vector dist(h, vector(w, vector(4, INF)));
    pq.emplace(0, 0, 0, 0);
    dist[0][0][0] = 0;
    while (!pq.empty()) {
        auto [cost, x, y, d] = pq.top();
        pq.pop();
        if (dist[x][y][d] < cost) {
            continue;
        }
        for (int i = 0; i < 4; i++) {
            int nd = (d + i) % 4;
            int nx = x + dx[nd];
            int ny = y + dy[nd];
            if (nx < 0 || nx >= h || ny < 0 || ny >= w) {
                continue;
            }
            int next_cost = cost + (grid[x][y] == i ? 0 : c[i]);
            if (dist[nx][ny][nd] > next_cost) {
                dist[nx][ny][nd] = next_cost;
                pq.emplace(next_cost, nx, ny, nd);
            }
        }
    }

    int ans = *ranges::min_element(dist[h - 1][w - 1]);
    cout << (ans == INF ? -1 : ans) << endl;
}

int main() {
    while (true) {
        int w, h;
        cin >> w >> h;
        if (w == 0 && h == 0) {
            break;
        }

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

        solve(w, h, s, c);
    }
}
accuracy: 1
time_ms: 10
memory_kb: 3712
final_rank: 10

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;

const int INF = 2e9;
int dx[]      = {0, 1, 0, -1};
int dy[]      = {1, 0, -1, 0};

void solve(int w, int h, vector<vector<int>> grid, vector<int> c) {
    priority_queue<tuple<int, int, int, int>, vector<tuple<int, int, int, int>>, greater<>> pq;
    vector dist(h, vector(w, vector(4, INF)));
    pq.emplace(0, 0, 0, 0);
    dist[0][0][0] = 0;
    while (!pq.empty()) {
        auto [cost, x, y, d] = pq.top();
        pq.pop();
        if (dist[x][y][d] < cost) {
            continue;
        }
        for (int i = 0; i < 4; i++) {
            int nd = (d + i) % 4;
            int nx = x + dx[nd];
            int ny = y + dy[nd];
            if (nx < 0 || nx >= h || ny < 0 || ny >= w) {
                continue;
            }
            int next_cost = cost + (grid[x][y] == i ? 0 : c[i]);
            if (dist[nx][ny][nd] > next_cost) {
                dist[nx][ny][nd] = next_cost;
                pq.emplace(next_cost, nx, ny, nd);
            }
        }
    }

    int ans = INF;
    for (int dir = 0; dir < 4; dir++) {
        ans = min(ans, dist[h - 1][w - 1][dir]);
    }
    cout << (ans == INF ? -1 : ans) << endl;
}

int main() {
    while (true) {
        int w, h;
        cin >> w >> h;
        if (w == 0 && h == 0) {
            break;
        }

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

        solve(w, h, s, c);
    }
}
accuracy: 1
time_ms: 10
memory_kb: 3712
final_rank: 10

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;

const int INF = 2e9;
int dx[]      = {0, 1, 0, -1};
int dy[]      = {1, 0, -1, 0};

void solve(int w, int h, vector<vector<int>> grid, vector<int> c) {
    priority_queue<tuple<int, int, int, int>, vector<tuple<int, int, int, int>>, greater<>> pq;
    vector dist(h, vector(w, vector(4, INF)));
    pq.emplace(0, 0, 0, 0);
    dist[0][0][0] = 0;
    while (!pq.empty()) {
        auto [cost, x, y, d] = pq.top();
        pq.pop();

        if (dist[x][y][d] < cost) {
            continue;
        }

        for (int i = 0; i < 4; i++) {
            // 命令通りに行動する場合(コスト0)
            if (grid[x][y] == i) {
                int nd = (d + grid[x][y]) % 4;
                int nx = x + dx[nd];
                int ny = y + dy[nd];
                if (nx < 0 || nx >= h || ny < 0 || ny >= w) {
                    continue;
                }
                if (dist[nx][ny][nd] > cost) {
                    dist[nx][ny][nd] = cost;
                    pq.emplace(cost, nx, ny, nd);
                }
            } else {
                // 別の命令を行う場合(コストci)
                int nd = (d + i) % 4;
                int nx = x + dx[nd];
                int ny = y + dy[nd];
                if (nx < 0 || nx >= h || ny < 0 || ny >= w) {
                    continue;
                }
                int next_cost = cost + c[i];
                if (dist[nx][ny][nd] > next_cost) {
                    dist[nx][ny][nd] = next_cost;
                    pq.emplace(next_cost, nx, ny, nd);
                }
            }
        }
    }

    int ans = INF;
    for (int dir = 0; dir < 4; dir++) {
        ans = min(ans, dist[h - 1][w - 1][dir]);
    }
    cout << (ans == INF ? -1 : ans) << endl;
}

int main() {
    while (true) {
        int w, h;
        cin >> w >> h;
        if (w == 0 && h == 0) {
            break;
        }

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

        solve(w, h, s, c);
    }
}
accuracy: 1
time_ms: 10
memory_kb: 3840
final_rank: 14

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
#define rep(i, n) for (ll i = 0; i < (ll)(n); i++)
#define rrep(i,start,end) for (ll i = start;i >= (ll)(end);i--)
#define repn(i,end) for(ll i = 0; i <= (ll)(end); i++)
#define reps(i,start,end) for(ll i = start; i < (ll)(end); i++)
#define repsn(i,start,end) for(ll i = start; i <= (ll)(end); i++)
#define each(p,a) for(auto &p:a)
typedef vector<ll> vll;
typedef vector<pair<ll ,ll>> vpll;
typedef vector<vector<ll>> vvll;
typedef set<ll> sll;
typedef map<ll , ll> mpll;
typedef pair<ll ,ll> pll;
typedef tuple<ll , ll , ll> tpl3;
#define LL(...) ll __VA_ARGS__; input(__VA_ARGS__)
#define LD(...) ld __VA_ARGS__; input(__VA_ARGS__)
#define Str(...) string __VA_ARGS__; input(__VA_ARGS__)
#define Ch(...) char __VA_ARGS__; input(__VA_ARGS__)
#define all(a)  (a).begin(),(a).end()
#define UNIQUE(v) v.erase( unique(v.begin(), v.end()), v.end() );
#define sz(x) (ll)x.size()
// << std::fixed << std::setprecision(10)
const ll INF = 1LL << 60;
const ld EPS = 1e-9;
 
ll lceil(ll a,ll b){if(a%b==0){return a/b;}if(a>=0){return (a/b)+1;}else{return -((-a)/b);}}
ll lfloor(ll a,ll b){if(a%b==0){return a/b;}if(a>=0){return (a/b);}else{return -((-a)/b)-1;}}
inline ll positive_mod(ll a,ll m){return (a % m + m)%m;}
inline ll popcnt(ull a){ return __builtin_popcountll(a);}
//0indexed
inline ll topbit(ll a){assert(a != 0);return 63 - __builtin_clzll(a);}
inline ll smlbit(ll a){assert(a != 0);return __builtin_ctzll(a);}
template<class T> bool chmin(T& a, T b){if(a > b){a = b;return true;}return false;}
template<class T> bool chmax(T& a, T b){if(a < b){a = b;return true;}return false;}
template<typename T> std::istream &operator>>(std::istream&is,std::vector<T>&v){for(T &in:v){is>>in;}return is;}
template<typename T> std::ostream &operator<<(std::ostream&os,const std::vector<T>&v){for(auto it=std::begin(v);it!=std::end(v);){os<<*it<<((++it)!=std::end(v)?" ":"");}return os;}
template<typename T1, typename T2>std::ostream &operator<< (std::ostream &os, std::pair<T1,T2> p){os << "{" << p.first << "," << p.second << "}";return os;}
template<class... T>void input(T&... a){(cin >> ... >> a);}
void print(){cout << endl;}
template<class T, class... Ts>void print(const T& a, const Ts&... b){cout << a;((cout << ' ' << b), ...);cout << endl;}
template<class T> void pspace(const T& a){ cout << a << ' ';}
void perr(){cerr << endl;}
template<class T, class... Ts>void perr(const T& a, const Ts&... b){cerr << a;((cerr << ' ' << b), ...);cerr << endl;}
void yes(bool i = true){ return print(i?"yes":"no"); }
void Yes(bool i = true){ return print(i?"Yes":"No"); }
void YES(bool i = true){ return print(i?"YES":"NO"); }
template <class T> vector<T> &operator++(vector<T> &v) {for(auto &e : v) e++;return v;}
template <class T> vector<T> operator++(vector<T> &v, signed) {auto res = v;for(auto &e : v) e++;return res;}
template <class T> vector<T> &operator--(vector<T> &v) {for(auto &e : v) e--;return v;}
template <class T> vector<T> operator--(vector<T> &v, signed) {auto res = v;for(auto &e : v) e--;return res;}
//grid探索用
vector<ll> _ta = {0,1,0,-1,1,1,-1,-1};
vector<ll> _yo = {1,0,-1,0,1,-1,1,-1};
bool isin(ll now_i,ll now_j,ll h,ll w){return (0<=now_i && now_i < h && 0 <= now_j && now_j < w);}
  
ll lpow(ll x,ll n){ll ans = 1;while(n >0){if(n & 1)ans *= x;x *= x;n >>= 1;}return ans;}
ll Modlpow(ll x,ll n,ll m){ll ans = 1;ll a = x%m;while(n >0){if(n & 1){ans *= a;ans%= m;}a *= a;a %= m;n >>= 1;}return ans;} 
const ll MOD9 = 998244353LL;
const ll MOD10 = 1000000007LL;

void solve(ll h,ll w){
  vvll g(h,vll(w));
  rep(i,h)cin >> g[i];
  vll c(4);cin >> c;

  vector<vvll> dist(h,vvll(w,vll(4,INF)));
  using tpl4 = tuple<ll,ll,ll,ll>;
  priority_queue<tpl4,vector<tpl4>,greater<tpl4>> pq;
  // 0,1,2,3 : 右下左上
  dist[0][0][0] = 0;
  pq.push({0,0,0,0});
  while(!pq.empty()){
    auto[cost,y,x,d] = pq.top();
    pq.pop();
    if(g[y][x] < 4){
      ll nd = (d+g[y][x])%4;
      ll ny = y + _ta[nd];
      ll nx = x + _yo[nd];
      if(isin(ny,nx,h,w) && dist[ny][nx][nd] > cost){
        dist[ny][nx][nd] = cost;
        pq.push({dist[ny][nx][nd],ny,nx,nd});
      }
    }
    rep(i,4){
      ll nd = (d+i)%4;
      ll ny = y + _ta[nd];
      ll nx = x + _yo[nd];
      if(isin(ny,nx,h,w) && dist[ny][nx][nd] > cost + c[i]){
        dist[ny][nx][nd] = cost + c[i];
        pq.push({dist[ny][nx][nd],ny,nx,nd});
      }
    }
  }
  ll ans = INF;
  rep(i,4){
    chmin(ans,dist[h-1][w-1][i]);
  }
  cout << ans << endl;
}
 
int main(){
  ios::sync_with_stdio(false);cin.tie(nullptr);
  while(true){
    LL(w,h);
    if(w == 0 && h == 0)break;
    solve(h,w);
  }
}
accuracy: 1
time_ms: 10
memory_kb: 3968
final_rank: 16

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define all(a) (a).begin(), (a).end()
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define rrep(i, n) for (int i = (int)(n); i >= 0; i--)
#define range(i, l, r) for (int i = (int)(l); i < (int)(r); i++)
using ll = long long;

template <typename T>
ostream& operator<<(ostream& os, const vector<T>& v) {
    os << "[";
    for (int i = 0; i < v.size(); i++) {
        os << v[i] << (i == (v.size() - 1) ? "" : ", ");
    }
    os << "]";
    return os;
}

template <typename T1, typename T2>
ostream& operator<<(ostream& os, const pair<T1, T2> p) {
    os << "{" << p.first << ", " << p.second << "}";
    return os;
}

bool solve() {
    int w, h;
    cin >> w >> h;
    if (w == 0) return false;

    int s[h][w];
    rep(i, h) rep(j, w) cin >> s[i][j];

    int cost[4], _cost[4];
    rep(i, 4) {
        cin >> cost[i];
        _cost[i] = cost[i];
    }

    vector<pair<int, int>> dir = {{0, 1}, {-1, 0}, {0, -1}, {1, 0}};
    int dp[h][w][4];
    int inf = 1 << 20;
    rep(i, h) rep(j, w) rep(k, 4) dp[i][j][k] = inf;
    dp[0][0][0] = 0;

    priority_queue<array<int, 4>> pq{};
    pq.push({0, 0, 0, 0});
    while (!pq.empty()) {
        auto [d, i, j, k] = pq.top();
        pq.pop();
        d = -d;
        if (s[i][j] < 4) cost[s[i][j]] = 0;
        rep(x, 4) {
            k = (k + 4 - x) % 4;
            auto [di, dj] = dir[k];
            if (0 <= i + di && i + di < h && 0 <= j + dj && j + dj < w) {
                if (dp[i + di][j + dj][k] > d + cost[x]) {
                    dp[i + di][j + dj][k] = d + cost[x];
                    pq.push({-d - cost[x], i + di, j + dj, k});
                }
            }
            k = (k + x) % 4;
        }
        if (s[i][j] < 4) cost[s[i][j]] = _cost[s[i][j]];
    }

    int ans = inf;
    rep(x, 4) ans = min(ans, dp[h - 1][w - 1][x]);
    cout << ans << endl;
    return true;
}

int main() {
    while (solve()) {
    }
}
accuracy: 1
time_ms: 10
memory_kb: 3584
final_rank: 6

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define rrep(i, a, b) for (int i = (int)(b)-1; i >= (int)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}

#include <unistd.h>

namespace fastio {
static constexpr uint32_t SZ = 1 << 17;
char ibuf[SZ];
char obuf[SZ];
char out[100];
// pointer of ibuf, obuf


uint32_t pil = 0, pir = 0, por = 0;

struct Pre {
    char num[10000][4];
    constexpr Pre() : num() {
        for (int i = 0; i < 10000; i++) {
            int n = i;
            for (int j = 3; j >= 0; j--) {
                num[i][j] = n % 10 | '0';
                n /= 10;
            }
        }
    }
} constexpr pre;

inline void load() {
    memmove(ibuf, ibuf + pil, pir - pil);
    pir = pir - pil + fread(ibuf + pir - pil, 1, SZ - pir + pil, stdin);
    pil = 0;
    if (pir < SZ)
        ibuf[pir++] = '\n';
}

inline void flush() {
    fwrite(obuf, 1, por, stdout);
    por = 0;
}

void rd(char &c) {
    do {
        if (pil + 1 > pir)
            load();
        c = ibuf[pil++];
    } while (isspace(c));
}

void rd(string &x) {
    x.clear();
    char c;
    do {
        if (pil + 1 > pir)
            load();
        c = ibuf[pil++];
    } while (isspace(c));
    do {
        x += c;
        if (pil == pir)
            load();
        c = ibuf[pil++];
    } while (!isspace(c));
}

template <typename T> void rd_real(T &x) {
    string s;
    rd(s);
    x = stod(s);
}

template <typename T> void rd_integer(T &x) {
    if (pil + 100 > pir)
        load();
    char c;
    do
        c = ibuf[pil++];
    while (c < '-');
    bool minus = 0;
    if constexpr (is_signed<T>::value || is_same_v<T, i128>) {
        if (c == '-') {
            minus = 1, c = ibuf[pil++];
        }
    }
    x = 0;
    while ('0' <= c) {
        x = x * 10 + (c & 15), c = ibuf[pil++];
    }
    if constexpr (is_signed<T>::value || is_same_v<T, i128>) {
        if (minus)
            x = -x;
    }
}

void rd(int &x) {
    rd_integer(x);
}
void rd(ll &x) {
    rd_integer(x);
}
void rd(i128 &x) {
    rd_integer(x);
}
void rd(uint &x) {
    rd_integer(x);
}
void rd(ull &x) {
    rd_integer(x);
}
void rd(u128 &x) {
    rd_integer(x);
}
void rd(double &x) {
    rd_real(x);
}
void rd(long double &x) {
    rd_real(x);
}

template <class T, class U> void rd(pair<T, U> &p) {
    return rd(p.first), rd(p.second);
}
template <size_t N = 0, typename T> void rd_tuple(T &t) {
    if constexpr (N < std::tuple_size<T>::value) {
        auto &x = std::get<N>(t);
        rd(x);
        rd_tuple<N + 1>(t);
    }
}
template <class... T> void rd(tuple<T...> &tpl) {
    rd_tuple(tpl);
}

template <size_t N = 0, typename T> void rd(array<T, N> &x) {
    for (auto &d : x)
        rd(d);
}
template <class T> void rd(vector<T> &x) {
    for (auto &d : x)
        rd(d);
}

void read() {}
template <class H, class... T> void read(H &h, T &...t) {
    rd(h), read(t...);
}

void wt(const char c) {
    if (por == SZ)
        flush();
    obuf[por++] = c;
}
void wt(const string s) {
    for (char c : s)
        wt(c);
}
void wt(const char *s) {
    size_t len = strlen(s);
    for (size_t i = 0; i < len; i++)
        wt(s[i]);
}

template <typename T> void wt_integer(T x) {
    if (por > SZ - 100)
        flush();
    if (x < 0) {
        obuf[por++] = '-', x = -x;
    }
    int outi;
    for (outi = 96; x >= 10000; outi -= 4) {
        memcpy(out + outi, pre.num[x % 10000], 4);
        x /= 10000;
    }
    if (x >= 1000) {
        memcpy(obuf + por, pre.num[x], 4);
        por += 4;
    } else if (x >= 100) {
        memcpy(obuf + por, pre.num[x] + 1, 3);
        por += 3;
    } else if (x >= 10) {
        int q = (x * 103) >> 10;
        obuf[por] = q | '0';
        obuf[por + 1] = (x - q * 10) | '0';
        por += 2;
    } else
        obuf[por++] = x | '0';
    memcpy(obuf + por, out + outi + 4, 96 - outi);
    por += 96 - outi;
}

template <typename T> void wt_real(T x) {
    ostringstream oss;
    oss << fixed << setprecision(15) << double(x);
    string s = oss.str();
    wt(s);
}

void wt(int x) {
    wt_integer(x);
}
void wt(ll x) {
    wt_integer(x);
}
void wt(i128 x) {
    wt_integer(x);
}
void wt(uint x) {
    wt_integer(x);
}
void wt(ull x) {
    wt_integer(x);
}
void wt(u128 x) {
    wt_integer(x);
}
void wt(double x) {
    wt_real(x);
}
void wt(long double x) {
    wt_real(x);
}

template <class T, class U> void wt(const pair<T, U> val) {
    wt(val.first);
    wt(' ');
    wt(val.second);
}
template <size_t N = 0, typename T> void wt_tuple(const T t) {
    if constexpr (N < std::tuple_size<T>::value) {
        if constexpr (N > 0) {
            wt(' ');
        }
        const auto x = std::get<N>(t);
        wt(x);
        wt_tuple<N + 1>(t);
    }
}
template <class... T> void wt(tuple<T...> tpl) {
    wt_tuple(tpl);
}
template <class T, size_t S> void wt(const array<T, S> val) {
    auto n = val.size();
    for (size_t i = 0; i < n; i++) {
        if (i)
            wt(' ');
        wt(val[i]);
    }
}
template <class T> void wt(const vector<T> val) {
    auto n = val.size();
    for (size_t i = 0; i < n; i++) {
        if (i)
            wt(' ');
        wt(val[i]);
    }
}

void print() {
    wt('\n');
}
template <class Head, class... Tail> void print(Head &&head, Tail &&...tail) {
    wt(head);
    if (sizeof...(Tail))
        wt(' ');
    print(forward<Tail>(tail)...);
}
void __attribute__((destructor)) _d() {
    flush();
}
} // namespace fastio


using fastio::flush;
using fastio::print;
using fastio::read;

inline void first(bool i = true) {
    print(i ? "first" : "second");
}
inline void Alice(bool i = true) {
    print(i ? "Alice" : "Bob");
}
inline void Takahashi(bool i = true) {
    print(i ? "Takahashi" : "Aoki");
}
inline void yes(bool i = true) {
    print(i ? "yes" : "no");
}
inline void Yes(bool i = true) {
    print(i ? "Yes" : "No");
}
inline void No() {
    print("No");
}
inline void YES(bool i = true) {
    print(i ? "YES" : "NO");
}
inline void NO() {
    print("NO");
}
inline void Yay(bool i = true) {
    print(i ? "Yay!" : ":(");
}
inline void Possible(bool i = true) {
    print(i ? "Possible" : "Impossible");
}
inline void POSSIBLE(bool i = true) {
    print(i ? "POSSIBLE" : "IMPOSSIBLE");
}

/**
 * @brief Fast IO
 */

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

int main() {
while(1) {
    int N, M;
    cin >> M >> N;
    if (N == 0 && M == 0) return 0;
    vector<vector<int>> A(N,vector<int>(M));
    rep(i,0,N) {
        rep(j,0,M) {
            char C;
            cin >> C;
            A[i][j] = C - '0';
        }
    }
    int Cost[4];
    rep(i,0,4) cin >> Cost[i];
    vector DP(N, vector(M, vector<int>(4,inf)));
    priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>> PQ;
    auto encode = [&](int i, int j, int k) -> int {
        return i * M * 4 + j * 4 + k;
    };
    auto decode = [&](int a) -> tuple<int,int,int> {
        return {a / (M * 4), (a / 4) % M, a % 4};
    };
    DP[0][0][0] = 0;
    PQ.push({0,encode(0,0,0)});
    while(!PQ.empty()) {
        pair<int,int> P = PQ.top();
        PQ.pop();
        int C = P.first;
        auto [X, Y, dir] = decode(P.second);
        if (DP[X][Y][dir] < C) continue;
        rep(i,0,4) {
            int NC;
            if (i == A[X][Y]) NC = C;
            else NC = C + Cost[i];
            int Ndir = (dir + i) % 4;
            int NX = X + dx[Ndir], NY = Y + dy[Ndir];
            if (0 <= NX && NX < N && 0 <= NY && NY < M) {
                if (chmin(DP[NX][NY][Ndir],NC)) {
                    PQ.push({NC, encode(NX,NY,Ndir)});
                }
            }
        }
    }
    int ANS = inf;
    rep(i,0,4) {
        chmin(ANS, DP[N-1][M-1][i]);
    }
    cout << ANS << endl;
}
}
accuracy: 1
time_ms: 10
memory_kb: 3520
final_rank: 3

code_snippet: #include<bits/stdc++.h>
//#include <atcoder/all>
using namespace std;
//using namespace atcoder;

#define all(v) v.begin(),v.end()
using ll = long long;
using ull = unsigned long long;
using vll=vector<ll>;
using vvll = vector<vector<ll>>;
using P = pair<ll,ll>;
using PP=pair<ll,pair<P,ll>>;
using vp=vector<pair<ll, ll>>;
//using mint=modint1000000007;
//using mint=modint998244353;

const ll INF=1ll<<60;
ll mod10=1e9+7;
ll mod99=998244353;
const double PI = acos(-1);

#define rep(i,n) for (ll i=0;i<n;++i)
#define per(i,n) for(ll i=n-1;i>=0;--i)
#define rep2(i,a,n) for (ll i=a;i<n;++i)
#define per2(i,a,n) for (ll i=a;i>=n;--i)

template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return true; } return false; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return true; } return false; }
vector<ll> dx={1,0,-1,0,-1,-1,1,1,0},dy={0,1,0,-1,-1,1,-1,1,0};

bool solve(){
    ll H,W;cin>>W>>H;
    if(H==W&&H==0) return 0;
    vvll A(H,vll(W));
    rep(i,H) rep(j,W) cin>>A[i][j];
    vll C(4);rep(i,4) cin>>C[i];

    vector dist(H,vvll(W,vll(4,INF)));
    priority_queue<PP,vector<PP>,greater<PP>> pq;
    pq.push({0,{{0,0},1}});
    while(pq.size()){
        auto [c,in]=pq.top();pq.pop();
        auto [now,d]=in;
        auto [nowi,nowj]=now;
        if(dist[nowi][nowj][d]!=INF) continue;
    // cout << nowi<<" "<<nowj<<" "<<c<<" "<<A[nowi][nowj] << endl;
        
        dist[nowi][nowj][d]=c;
        if(A[nowi][nowj]!=4){
            ll d2=(d-A[nowi][nowj]+4)%4;
            ull toi=nowi+dx[d2],toj=nowj+dy[d2];
          
            if((toi<H&&toj<W))pq.push({c,{{toi,toj},d2}});;
         
        }
        rep(k,4){
            ll d2=(d-k+4)%4;
            ull toi=nowi+dx[d2],toj=nowj+dy[d2];
            if(!(toi<H&&toj<W)) continue;
            pq.push({c+C[k],{{toi,toj},d2}});
        }
    }

    ll ans=INF;
    rep(i,4) chmin(ans,dist[H-1][W-1][i]);
    cout << ans << endl;

    return 1;
}



int main(){
   cin.tie(0);
   ios::sync_with_stdio(false);
   while(solve());
}
accuracy: 1
time_ms: 40
memory_kb: 3928
final_rank: 19

code_snippet: #include <bits/stdc++.h>
//#include <atcoder/all>
using ll = long long;
#define MOD 1000000007
#define Mod 998244353
const int MAX = 1000000005;
const long long INF = 1000000000000000005LL;
using namespace std;
//using namespace atcoder;

int di[] = {0, 1, 0, -1}, dj[] = {1, 0, -1, 0};
using i_i_i_i = tuple<int, int, int, int>;

bool solve() {
    int w, h;
    cin >> w >> h;
    if (h == 0 && w == 0) return false;
    vector<vector<int>> G(h, vector<int>(w));
    for (int i = 0; i < h; i++) {
        for (int j = 0; j < w; j++) cin >> G[i][j];
    }
    vector<int> c(4);
    for (int i = 0; i < 4; i++) cin >> c[i];
    vector<vector<vector<int>>> dist(h, vector<vector<int>>(w, vector<int>(4, MAX)));
    dist[0][0][0] = 0;
    priority_queue<i_i_i_i, vector<i_i_i_i>, greater<i_i_i_i>> pq;
    pq.push({0, 0, 0, 0});
    while (pq.size()) {
        auto [d, i, j, dir] = pq.top();
        pq.pop();
        if (d != dist[i][j][dir]) continue;
        for (int k = 0; k < 4; k++) {
            int ndir = (dir + k)%4, ni = i + di[ndir], nj = j + dj[ndir];
            if (ni < 0 || ni >= h || nj < 0 || nj >= w) continue;
            if (G[i][j] == k) {
                if (dist[ni][nj][ndir] <= dist[i][j][dir]) continue;
                dist[ni][nj][ndir] = dist[i][j][dir];
                pq.push({dist[ni][nj][ndir], ni, nj, ndir});
            } else {
                if (dist[ni][nj][ndir] <= dist[i][j][dir] + c[k]) continue;
                dist[ni][nj][ndir] = dist[i][j][dir] + c[k];
                pq.push({dist[ni][nj][ndir], ni, nj, ndir});
            }
        }
    }
    int ans = MAX;
    for (int i = 0; i < 4; i++) ans = min(ans, dist[h-1][w-1][i]);
    cout << ans << endl;
    return true;
}

int main() {
    ios::sync_with_stdio(0); cin.tie();
    while (solve()) {}
}
accuracy: 1
time_ms: 10
memory_kb: 3540
final_rank: 4

code_snippet: #include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < n; i++)
using namespace std;
void chmin(int &l, int r) {
    if (l > r) {
        l = r;
    }
}

bool solve() {
    int w, h; cin >> w >> h;
    if (w == 0 and h == 0) return false;
    vector C(h, vector<int>(w));
    rep(i, h) rep(j, w) cin >> C[i][j];
    int m = 4;
    vector<int> co(m); rep(i, m) cin >> co[i];
    int INF = 1001001001;
    vector dp(h, vector(w, vector(m + 1, INF)));
    vector<int> di = { 0, 1, 0, -1, 0 };
    vector<int> dj = { 1, 0, -1, 0, 0 };
    using S = tuple<int, int, int, int>;
    priority_queue<S, vector<S>, greater<S>> pq;
    dp[0][0][0] = 0;
    pq.emplace(0, 0, 0, 0);
    while (pq.size()) {
        auto [c, i, j, dir] = pq.top(); pq.pop();
        // cerr << c << " " << i << " " << j << " " << dir << endl;
        if (c != dp[i][j][dir]) continue;
        // change
        for (int k = 0; k < 4; k++) {
            int ndir = (dir + k) % 4;
            int ni = i + di[ndir];
            int nj = j + dj[ndir];
            if (ni < 0 or nj < 0 or ni >= h or nj >= w) continue;
            int nc = c + co[k];
            if (dp[ni][nj][ndir] <= nc) continue;
            dp[ni][nj][ndir] = nc;
            pq.emplace(nc, ni, nj, ndir);
        }
        if (C[i][j] < m) {
            int ndir = (dir + C[i][j]) % 4;
            int ni = i + di[ndir];
            int nj = j + dj[ndir];
            if (ni < 0 or nj < 0 or ni >= h or nj >= w) continue;
            // don't change
            if (dp[ni][nj][ndir] <= c) continue;
            dp[ni][nj][ndir] = c;
            pq.emplace(c, ni, nj, ndir);
        }
    }
    // rep(k, 5) {
    //     cerr << endl;
    //     rep(i, h) rep(j, w) {
    //         cerr << (dp[i][j][k] == INF ? -1 : dp[i][j][k]) << (j + 1 == w ? "\n" : " ");
    //     }
    // }
    int ans = INF;
    rep(i, 5) chmin(ans, dp[h - 1][w - 1][i]);
    if (ans == INF) ans = -1;
    cout << ans << endl;
    return true;
}

int main() {
    while (solve());
}
accuracy: 1
time_ms: 20
memory_kb: 3556
final_rank: 7

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for (int i = 0; i < (n); i++)
#ifdef Himesaka
#include <noachan.hpp>
#define debug(...) debug_print::multi_print(#__VA_ARGS__, __VA_ARGS__)
#else
#define debug(...) (static_cast<void>(0))
#endif
struct e
{
   int di{};
   int y{}, x{};
   int cost{};
};
bool is_out(int y, int x, int h, int w)
{
   return (!((0 <= y && y < h) && (0 <= x && x < w)));
}

template <class T>
bool chmin(T &a, const T &b)
{
   return a > b ? a = b, true : false;
}

pair<int, int> go_str(int y, int x, int dir)
{
   if (dir == 0)
      y--;
   if (dir == 1)
      x++;
   if (dir == 2)
      y++;
   if (dir == 3)
      x--;
   return make_pair(y, x);
}
int right(int d)
{
   d++;
   d %= 4;
   return d;
}
int left(int d)
{
   d += 3;
   d %= 4;
   return d;
}
int odd(int d)
{
   d += 2;
   d %= 4;
   return d;
}
int main()
{
   const int inf = INT_MAX / 2;
   for (;;)
   {
      int w, h;
      cin >> w >> h;
      if (!w && (!h))
         break;
      vector<vector<int>> s(h, vector<int>(w));
      rep(i, h) rep(j, w) cin >> s[i][j];

      vector<int> c(4);
      rep(i, 4) cin >> c[i];

      // y,x,向き(0上,1右,2下,3左)

      int dist[h][w][4];
      rep(i, h) rep(j, w) rep(k, 4) dist[i][j][k] = inf;
      dist[0][0][1] = 0;

      int y = 0, x = 0;
      // dir,y,x,cost
      auto comp = [](const e &a, const e &b)
      {
         return a.cost < b.cost;
      };
      // multiset<e, decltype(comp)> q;
      multiset<e, decltype(comp)> q(comp);
      q.insert({1, y, x, 0});
      int ans = inf;
      while (q.size())
      {
         auto [dir, y, x, cost] = *q.begin();
         q.erase(q.begin());
         int ndir = dir;
         if (s[y][x] == 0)
         {
            // 直進
         }
         else if (s[y][x] == 1)
         {
            // 右折
            ndir = right(dir);
         }
         else if (s[y][x] == 2)
         {
            ndir = odd(dir);
         }
         else if (s[y][x] == 3)
         {
            ndir = left(dir);
         }
         else if (s[y][x] == 4)
         {
            // 停止
            rep(i, 4)
            {
               ndir = dir;
               if (i == s[y][x])
                  continue;
               if (i == 0)
               {
               }
               if (i == 1)
                  ndir = right(dir);
               if (i == 2)
                  ndir = odd(dir);
               if (i == 3)
                  ndir = left(dir);
               auto [ny, nx] = go_str(y, x, ndir);
               if (!is_out(ny, nx, h, w))
               {
                  if (ny == h - 1 && nx == w - 1)
                  {
                     chmin(ans, dist[y][x][dir] + c[i]);
                     continue;
                  }
                  if (chmin(dist[ny][nx][ndir], dist[y][x][dir] + c[i]))
                     q.insert({ndir, ny, nx, 0});
               }
            }
            continue;
         }
         auto [ny, nx] = go_str(y, x, ndir);
         if (!is_out(ny, nx, h, w))
         {
            if (ny == h - 1 && nx == w - 1)
            {
               chmin(ans, dist[y][x][dir]);
               continue;
            }
            if (chmin(dist[ny][nx][ndir], dist[y][x][dir]))
               q.insert({ndir, ny, nx, 0});
         }
         // コストを支払う場合
         // 直進
         rep(i, 4)
         {
            ndir = dir;
            if (i == s[y][x])
               continue;
            if (i == 0)
            {
            }
            if (i == 1)
               ndir = right(dir);
            if (i == 2)
               ndir = odd(dir);
            if (i == 3)
               ndir = left(dir);
            auto [ny, nx] = go_str(y, x, ndir);
            if (!is_out(ny, nx, h, w))
            {
               if (ny == h - 1 && nx == w - 1)
               {
                  chmin(ans, dist[y][x][dir] + c[i]);
                  continue;
               }
               if (chmin(dist[ny][nx][ndir], dist[y][x][dir] + c[i]))
                  q.insert({ndir, ny, nx, 0});
            }
         }
      }
      cout << ans << endl;
   }
}
accuracy: 1
time_ms: 100
memory_kb: 3492
final_rank: 13

code_snippet: #include <algorithm>
#include <cmath>
#include <cstdlib>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <unordered_set>
#include <vector>

#define INF (1000000000)

using namespace std;
using ll = long long;

template <typename T>
constexpr bool chmin(T& min, const T target) {
	if (target < min) {
		min = target;
		return true;
	}
	return false;
}

// 命令
// 0: 「直進」命令
// 1: 「右折」命令
// 2: 「反転」命令
// 3: 「左折」命令
// 4: 「停止」命令

// 方向
// 0: 右
// 1: 下
// 2: 左
// 3: 上

int main(void) {
	const int directions[4][2]{{0, 1}, {1, 0}, {0, -1}, {-1, 0}};

	while (true) {
		int W, H, costs[4];
		cin >> W >> H;
		if (W == 0) break;
		vector<vector<int>> commands(H, vector<int>(W));
		for (vector<int>& row : commands) {
			for (int& sqr : row) cin >> sqr;
		}
		for (int& cost : costs) cin >> cost;

		int count_done_goal = 0;
		int recent_done_r = 0, recent_done_c = 0, recent_done_d = 0;
		vector<vector<vector<int>>> distances(H, vector<vector<int>>(W, vector<int>(4, INF)));
		distances[recent_done_r][recent_done_c][recent_done_d] = 0;
		vector<vector<vector<bool>>> done(H, vector<vector<bool>>(W, vector<bool>(4, false)));
		done[recent_done_r][recent_done_c][recent_done_d] = true;
		while (true) {
			for (int cmd = 0; cmd < 4; cmd++) {
				int turn_to = (recent_done_d + cmd) % 4;
				int adjacent_r = recent_done_r + directions[turn_to][0];
				int adjacent_c = recent_done_c + directions[turn_to][1];
				if (adjacent_r < 0 || H <= adjacent_r || adjacent_c < 0 || W <= adjacent_c || done[adjacent_r][adjacent_c][turn_to]) continue;
				int new_distance = distances[recent_done_r][recent_done_c][recent_done_d];
				if (cmd != commands[recent_done_r][recent_done_c]) new_distance += costs[cmd];
				chmin(distances[adjacent_r][adjacent_c][turn_to], new_distance);
			}

			int min_distance = INF, min_r, min_c, min_d;
			for (int r = 0; r < H; r++) {
				for (int c = 0; c < W; c++) {
					for (int d = 0; d < 4; d++) {
						if (done[r][c][d]) continue;
						if (chmin(min_distance, distances[r][c][d])) {
							min_r = r;
							min_c = c;
							min_d = d;
						}
					}
				}
			}
			done[min_r][min_c][min_d] = true;
			recent_done_r = min_r;
			recent_done_c = min_c;
			recent_done_d = min_d;

			if (recent_done_r == H - 1 && recent_done_c == W - 1) {
				count_done_goal++;
				if (count_done_goal == 2) break;
			}
		}

		int min_distance_goal = INF;
		for (int d = 0; d < 4; d++) {
			chmin(min_distance_goal, distances[H - 1][W - 1][d]);
		}

		cout << min_distance_goal << endl;
	}

	return 0;
}
accuracy: 1
time_ms: 250
memory_kb: 3524
final_rank: 20

code_snippet: #include <algorithm>
#include <cmath>
#include <cstdlib>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <unordered_set>
#include <vector>

#define INF (1000000000)

using namespace std;
using ll = long long;

template <typename T>
constexpr bool chmin(T& min, const T target) {
	if (target < min) {
		min = target;
		return true;
	}
	return false;
}

// 命令
// 0: 「直進」命令
// 1: 「右折」命令
// 2: 「反転」命令
// 3: 「左折」命令
// 4: 「停止」命令

// 方向
// 0: 右
// 1: 下
// 2: 左
// 3: 上

int main(void) {
	const int directions[4][2]{{0, 1}, {1, 0}, {0, -1}, {-1, 0}};

	while (true) {
		int W, H, costs[4];
		cin >> W >> H;
		if (W == 0) break;
		vector<vector<int>> commands(H, vector<int>(W));
		for (vector<int>& row : commands) {
			for (int& sqr : row) cin >> sqr;
		}
		for (int& cost : costs) cin >> cost;

		int count_done_goal = 0;
		int recent_done_r = 0, recent_done_c = 0, recent_done_d = 0;
		vector<vector<vector<int>>> distances(H, vector<vector<int>>(W, vector<int>(4, INF)));
		distances[recent_done_r][recent_done_c][recent_done_d] = 0;
		vector<vector<vector<bool>>> done(H, vector<vector<bool>>(W, vector<bool>(4, false)));
		done[recent_done_r][recent_done_c][recent_done_d] = true;
		while (true) {
			for (int cmd = 0; cmd < 4; cmd++) {
				int turn_to = (recent_done_d + cmd) % 4;
				int adjacent_r = recent_done_r + directions[turn_to][0];
				int adjacent_c = recent_done_c + directions[turn_to][1];
				if (adjacent_r < 0 || H <= adjacent_r || adjacent_c < 0 || W <= adjacent_c || done[adjacent_r][adjacent_c][turn_to]) continue;
				int new_distance = distances[recent_done_r][recent_done_c][recent_done_d];
				if (cmd != commands[recent_done_r][recent_done_c]) new_distance += costs[cmd];
				chmin(distances[adjacent_r][adjacent_c][turn_to], new_distance);
			}

			int min_distance = INF, min_r, min_c, min_d;
			for (int r = 0; r < H; r++) {
				for (int c = 0; c < W; c++) {
					for (int d = 0; d < 4; d++) {
						if (done[r][c][d]) continue;
						if (chmin(min_distance, distances[r][c][d])) {
							min_r = r;
							min_c = c;
							min_d = d;

							if (r == 0 && c == 3 && d == 0) {
								cout;
							}
						}
					}
				}
			}
			done[min_r][min_c][min_d] = true;
			recent_done_r = min_r;
			recent_done_c = min_c;
			recent_done_d = min_d;

			// cout << recent_done_r << " " << recent_done_c << " " << recent_done_d << endl;

			if (recent_done_r == 0 && recent_done_c == 3 && recent_done_d == 0) {
				cout;
			}

			if (recent_done_r == H - 1 && recent_done_c == W - 1) count_done_goal++;
			if (count_done_goal == 2) break;
		}

		int min_distance_goal = INF;
		for (int d = 0; d < 4; d++) {
			chmin(min_distance_goal, distances[H - 1][W - 1][d]);
		}

		cout << min_distance_goal << endl;
	}

	return 0;
}
accuracy: 1
time_ms: 230
memory_kb: 3288
final_rank: 17

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
using P = pair<ll, ll>;
#define rep(i, a, b) for(ll i = a; i < b; ++i)
#define rrep(i, a, b) for(ll i = a; i >= b; --i)
constexpr ll inf = 4e18;
struct SetupIO {
    SetupIO() {
        ios::sync_with_stdio(0);
        cin.tie(0);
        cout << fixed << setprecision(30);
    }
} setup_io;
template <typename T = int>
struct Edge {
    int from, to;
    T cost;
    int idx;
    Edge()
        : from(-1), to(-1), cost(-1), idx(-1) {}
    Edge(int from, int to, T cost = 1, int idx = -1)
        : from(from), to(to), cost(cost), idx(idx) {}
    operator int() const {
        return to;
    }
};
template <typename T = int>
struct Graph {
    Graph(int N)
        : n(N), es(0), g(N) {}
    int size() const {
        return n;
    }
    int edge_size() const {
        return es;
    }
    void add_edge(int from, int to, T cost = 1) {
        assert(0 <= from and from < n);
        assert(0 <= to and to < n);
        g[from].emplace_back(from, to, cost, es);
        g[to].emplace_back(to, from, cost, es++);
    }
    void add_directed_edge(int from, int to, T cost = 1) {
        assert(0 <= from and from < n);
        assert(0 <= to and to < n);
        g[from].emplace_back(from, to, cost, es++);
    }
    inline vector<Edge<T>>& operator[](const int& k) {
        assert(0 <= k and k < n);
        return g[k];
    }
    inline const vector<Edge<T>>& operator[](const int& k) const {
        assert(0 <= k and k < n);
        return g[k];
    }

   private:
    int n, es;
    vector<vector<Edge<T>>> g;
};
template <typename T = int>
using Edges = vector<Edge<T>>;
template <typename T>
vector<pair<T, int>> dijkstra(const Graph<T>& g, const int s = 0) {
    int n = g.size();
    assert(0 <= s and s < n);
    vector<pair<T, int>> d(n, {numeric_limits<T>::max(), -1});
    priority_queue<pair<T, int>, vector<pair<T, int>>, greater<pair<T, int>>> pq;
    d[s] = {0, -1};
    pq.push({0, s});
    while(!pq.empty()) {
        pair<T, int> p = pq.top();
        pq.pop();
        T dist = p.first;
        int cur = p.second;
        if(d[cur].first < dist) continue;
        for(const Edge<T>& edge : g[cur]) {
            if(d[edge.to].first > d[cur].first + edge.cost) {
                d[edge.to] = {d[cur].first + edge.cost, cur};
                pq.push({d[edge.to].first, edge.to});
            }
        }
    }
    return d;
}
int main(void) {
    constexpr int dx[4] = {0, 1, 0, -1}, dy[4] = {1, 0, -1, 0};
    while(1) {
        int w, h;
        cin >> w >> h;
        if(w == 0 and h == 0) break;
        vector<vector<int>> s(h, vector<int>(w));
        Graph<int> g(h * w * 4);
        rep(i, 0, h) {
            rep(j, 0, w) {
                cin >> s[i][j];
            }
        }
        vector<int> c(4);
        rep(i, 0, 4) {
            cin >> c[i];
        }
        rep(i, 0, h) {
            rep(j, 0, w) {
                rep(k, 0, 4) {
                    rep(l, 0, 4) {
                        int nk = (k + l) % 4;
                        int ni = i + dx[nk], nj = j + dy[nk];
                        if(0 <= ni and ni < h and 0 <= nj and nj < w) {
                            g.add_directed_edge(i * w * 4 + j * 4 + k, ni * w * 4 + nj * 4 + nk, c[l]);
                        }
                    }
                }
                if(s[i][j] == 4) continue;
                rep(k, 0, 4) {
                    int nk = (k + s[i][j]) % 4;
                    int ni = i + dx[nk], nj = j + dy[nk];
                    if(0 <= ni and ni < h and 0 <= nj and nj < w) {
                        g.add_directed_edge(i * w * 4 + j * 4 + k, ni * w * 4 + nj * 4 + nk, 0);
                    }
                }
            }
        }
        auto d = dijkstra(g, 0);
        cout << min({d[4 * h * w - 4].first, d[4 * h * w - 3].first, d[4 * h * w - 2].first, d[4 * h * w - 1].first}) << '\n';
    }
}
accuracy: 1
time_ms: 20
memory_kb: 3980
final_rank: 18

code_snippet: // (⁠◕⁠ᴗ⁠◕⁠✿⁠)

// #pragma GCC target("avx2")
// #pragma GCC optimize("O3")
// #pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
#define rep(i, n) for (ll i = 0; i < (n); i++)
#define srep(i, s, n) for (ll i = s; i < (n); i++)
#define len(x) ((int)(x).size())
#define all(x) (x).begin(), (x).end()
using namespace std;
template<typename T> using vc = vector<T>;
template<typename T> using vv = vc<vc<T>>;
template<typename T> using vvv = vv<vc<T>>;
using vi = vc<int>;using vvi = vv<int>; using vvvi = vv<vi>;
using ll = long long;using vl = vc<ll>;using vvl = vv<ll>; using vvvl = vv<vl>;
using ld = long double; using vld = vc<ld>; using vvld = vc<vld>; using vvvld = vc<vvld>;
using uint = unsigned int;
using ull = unsigned long long;
const ld pi = 3.141592653589793;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
// const ll mod = 1000000007;
const ll mod = 998244353;
inline bool inside(ll y, ll x, ll H, ll W) {return 0 <= (y) and (y) < (H) and 0 <= (x) and (x) < (W); }

#define debug(var)  do{std::cout << #var << " : \n";view(var);}while(0)
template<typename T> void view(T e){cout << e << endl;}
template<typename T> void view(const vc<T>& v){for(const auto& e : v){ cout << e << " "; } cout << endl;}

vi dx = {-1, 0, 1, 0}, dy = {0, 1, 0, -1};

int solve(int h, int w){
    vvi A(h, vi(w)); rep(i, h) rep(j, w) cin >> A[i][j];
    vi C(4); rep(i, 4) cin >> C[i];
    vvvi dist(h, vvi(w, vi(4, inf)));
    dist[0][0][1] = 0;
    using P = tuple<int, int, int, int>;
    priority_queue<P, vc<P>, greater<P>> q;
    q.push({0, 0, 0, 1});
    while (!q.empty()){
        auto [d, x, y, k] = q.top(); q.pop();
        if (dist[x][y][k] < d) continue;
        int nx1 = x + dx[k], ny1 = y + dy[k];
        if (A[x][y] == 0 && inside(nx1, ny1, h, w) && dist[nx1][ny1][k] > d){
            dist[nx1][ny1][k] = d;
            q.push({d, nx1, ny1, k});
        }
        int nx2 = x + dx[(k + A[x][y]) % 4], ny2 = y + dy[(k + A[x][y]) % 4];
        if (0 < A[x][y] && A[x][y] < 4 && inside(nx2, ny2, h, w) && dist[nx2][ny2][(k + A[x][y]) % 4] > d){
            dist[nx2][ny2][(k + A[x][y]) % 4] = d;
            q.push({d, nx2, ny2, (k + A[x][y]) % 4});
        }

        if (inside(nx1, ny1, h, w) && dist[nx1][ny1][k] > d + C[0]){
            dist[nx1][ny1][k] = d + C[0];
            q.push({d + C[0], nx1, ny1, k});
        }
        srep(t, 1, 4){
            int nx3 = x + dx[(k + t) % 4], ny3 = y + dy[(k + t) % 4];
            if (inside(nx3, ny3, h, w) && dist[nx3][ny3][(k + t) % 4] > d + C[t]){
                dist[nx3][ny3][(k + t) % 4] = d + C[t];
                q.push({d + C[t], nx3, ny3, (k + t) % 4});
            }
        }
    }
    return min(min(dist[h - 1][w - 1][0], dist[h - 1][w - 1][1]), min(dist[h - 1][w - 1][2], dist[h - 1][w - 1][3]));
}

int main(){
    vi ans;
    while (true){
        int w, h;cin >> w >> h;
        if (w == 0) break;
        ans.push_back(solve(h, w));
    }
    for (auto x : ans) cout << x << endl;
}
accuracy: 1
time_ms: 10
memory_kb: 3512
final_rank: 2

code_snippet: #line 1 "a.cpp"
#define PROBLEM ""
#line 2 "/home/kuhaku/home/github/algo/lib/template/template.hpp"
#pragma GCC target("sse4.2,avx2,bmi2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
template <class T, class U>
bool chmax(T &a, const U &b) {
    return a < (T)b ? a = (T)b, true : false;
}
template <class T, class U>
bool chmin(T &a, const U &b) {
    return (T)b < a ? a = (T)b, true : false;
}
constexpr std::int64_t INF = 1000000000000000003;
constexpr int Inf = 1000000003;
constexpr int MOD = 1000000007;
constexpr int MOD_N = 998244353;
constexpr double EPS = 1e-7;
constexpr double PI = M_PI;
#line 3 "/home/kuhaku/home/github/algo/lib/template/macro.hpp"
#define FOR(i, m, n) for (int i = (m); i < int(n); ++i)
#define FORR(i, m, n) for (int i = (m)-1; i >= int(n); --i)
#define FORL(i, m, n) for (int64_t i = (m); i < int64_t(n); ++i)
#define rep(i, n) FOR (i, 0, n)
#define repn(i, n) FOR (i, 1, n + 1)
#define repr(i, n) FORR (i, n, 0)
#define repnr(i, n) FORR (i, n + 1, 1)
#define all(s) (s).begin(), (s).end()
#line 3 "/home/kuhaku/home/github/algo/lib/template/sonic.hpp"
struct Sonic {
    Sonic() {
        std::ios::sync_with_stdio(false);
        std::cin.tie(nullptr);
    }

    constexpr void operator()() const {}
} sonic;
#line 5 "/home/kuhaku/home/github/algo/lib/template/atcoder.hpp"
using namespace std;
using ll = std::int64_t;
using ld = long double;
template <class T, class U>
std::istream &operator>>(std::istream &is, std::pair<T, U> &p) {
    return is >> p.first >> p.second;
}
template <class T>
std::istream &operator>>(std::istream &is, std::vector<T> &v) {
    for (T &i : v) is >> i;
    return is;
}
template <class T, class U>
std::ostream &operator<<(std::ostream &os, const std::pair<T, U> &p) {
    return os << '(' << p.first << ',' << p.second << ')';
}
template <class T>
std::ostream &operator<<(std::ostream &os, const std::vector<T> &v) {
    for (auto it = v.begin(); it != v.end(); ++it) {
        os << (it == v.begin() ? "" : " ") << *it;
    }
    return os;
}
template <class Head, class... Tail>
void co(Head &&head, Tail &&...tail) {
    if constexpr (sizeof...(tail) == 0) std::cout << head << '\n';
    else std::cout << head << ' ', co(std::forward<Tail>(tail)...);
}
template <class Head, class... Tail>
void ce(Head &&head, Tail &&...tail) {
    if constexpr (sizeof...(tail) == 0) std::cerr << head << '\n';
    else std::cerr << head << ' ', ce(std::forward<Tail>(tail)...);
}
template <typename T, typename... Args>
auto make_vector(T x, int arg, Args... args) {
    if constexpr (sizeof...(args) == 0) return std::vector<T>(arg, x);
    else return std::vector(arg, make_vector<T>(x, args...));
}
void setp(int n) {
    std::cout << std::fixed << std::setprecision(n);
}
void Yes(bool is_correct = true) {
    std::cout << (is_correct ? "Yes" : "No") << '\n';
}
void No(bool is_not_correct = true) {
    Yes(!is_not_correct);
}
void YES(bool is_correct = true) {
    std::cout << (is_correct ? "YES" : "NO") << '\n';
}
void NO(bool is_not_correct = true) {
    YES(!is_not_correct);
}
void Takahashi(bool is_correct = true) {
    std::cout << (is_correct ? "Takahashi" : "Aoki") << '\n';
}
void Aoki(bool is_not_correct = true) {
    Takahashi(!is_not_correct);
}
#line 3 "a.cpp"

int main(void) {
    while (true) {
        int h, w;
        cin >> h >> w;
        if (!h)
            break;
        swap(h, w);
        vector<vector<int>> b(h, vector<int>(w));
        cin >> b;
        vector<int> c(4);
        cin >> c;
        auto in_field = [&](int x, int y) {
            return 0 <= x && x < h && 0 <= y && y < w;
        };
        vector<pair<int, int>> adj = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
        vector dp(h, vector(w, vector(4, INF)));
        priority_queue<tuple<int, int, int, int>, vector<tuple<int, int, int, int>>, greater<>> pq;
        dp[0][0][0] = 0;
        pq.emplace(0, 0, 0, 0);
        while (!pq.empty()) {
            auto [d, x, y, dir] = pq.top();
            pq.pop();
            if (dp[x][y][dir] < d)
                continue;
            rep (k, 4) {
                int nx = x, ny = y, nd = dir, nc = d;
                (nd += k) %= 4;
                nx += adj[nd].first, ny += adj[nd].second;
                if (!in_field(nx, ny))
                    continue;
                if (k != b[x][y])
                    nc += c[k];
                if (chmin(dp[nx][ny][nd], nc))
                    pq.emplace(nc, nx, ny, nd);
            }
        }

        ll ans = INF;
        rep (i, 4) chmin(ans, dp[h - 1][w - 1][i]);
        co(ans);
    }

    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3596
final_rank: 9

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rng(i, l, r) for(int i = int(l); i < int(r); i++)
#define rep(i, n) rng(i, 0, n)
#define sz(v) int(v.size())
#define foa(s, v) for(auto &s : v)
#define all(v) v.begin(), v.end()
template <class T>
using V = vector<T>;

template <class T>
bool chmin(T &a, T b) {
	return a > b ? a = b, 1 : 0;
}
template <class T>
bool chmax(T &a, T b) {
	return a < b ? a = b, 1 : 0;
}

int n;
void solve() {
	int w = n;
	int h;
	cin >> h;

	vector<int> dx = {0, 1, 0, -1};
	vector<int> dy = {1, 0, -1, 0};

	vector<vector<int>> grid(h, vector<int>(w));
	foa(r, grid) foa(c, r) cin >> c;

	vector<ll> costs(4);
	foa(c, costs) cin >> c;

	vector ids(4, vector(h, vector(w, 0)));
	int ver = 0;
	foa(r, ids) foa(c, r) foa(cc, c) cc = ver++;
	vector<tuple<int, int, int>> states;
	rep(dir, 4) rep(i, h) rep(j, w) { states.emplace_back(dir, i, j); }

	const int start = ids[0][0][0];

	using p = pair<ll, int>;
	priority_queue<p, vector<p>, greater<p>> q;
	constexpr ll INF = 1e15;
	vector<ll> dist(ver, INF);
	auto update = [&](int nxt, ll val) -> void {
		if(chmin(dist[nxt], val)) { q.emplace(dist[nxt], nxt); }
	};
	update(start, 0LL);

	while(q.size()) {
		ll d;
		int now;
		tie(d, now) = q.top();
		q.pop();
		if(d > dist[now]) continue;

		int dir, x, y;
		tie(dir, x, y) = states[now];

		if(x == h - 1 && y == w - 1) {
			cout << d << endl;
			return;
		}

		rep(command, 4) {
			int nxt_dir = (dir + command) % 4;
			int nx = x + dx[nxt_dir];
			if(nx < 0 || nx >= h) continue;
			int ny = y + dy[nxt_dir];
			if(ny < 0 || ny >= w) continue;

			update(ids[nxt_dir][nx][ny], d + (grid[x][y] == command ? 0 : costs[command]));
		}
	}

	assert(false);
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	// cout << fixed << setprecision(15);
	// srand((unsigned)time(NULL));
	while(cin >> n && n) solve();
}
accuracy: 1
time_ms: 10
memory_kb: 3556
final_rank: 5

code_snippet: #include "bits/stdc++.h"
using namespace std;
int W, H;
void solve() {
	vector<vector<int>> V(H, vector<int>(W));
	for(auto&& v: V) {
		for(auto&& e: v) {
			cin >> e;
		}
	}
	vector<int> C(4);
	cin >> C[0] >> C[1] >> C[2] >> C[3];
	vector<int> dx = { 1, 0, -1, 0 };
	vector<int> dy = { 0, 1, 0, -1 };
	using P = tuple<long long, int, int, int>;
	priority_queue<P, vector<P>, greater<>> Q;
	vector<vector<vector<long long>>> dist(
		H,
		vector<vector<long long>>(W, vector<long long>(4)));
	for(int i = 0; i < H; i++) {
		for(int j = 0; j < W; j++) {
			for(int d = 0; d < 4; d++) {
				dist[i][j][d] = (long long) (1e18);
			}
		}
	}
	Q.emplace(0, 0, 0, 0);
	dist[0][0][0] = 0;
	auto checkIndex = [&](int y, int x) -> bool {
		if(y < 0 || y >= H) return false;
		if(x < 0 || x >= W) return false;
		return true;
	};
	while(!Q.empty()) {
		auto [c, y, x, d] = Q.top();
		Q.pop();
		if(dist[y][x][d] < c) continue;
		for(int operation = 0; operation < 4; operation++) {
			int ny = y + dy[(d + operation) % 4];
			int nx = x + dx[(d + operation) % 4];
			if(!checkIndex(ny, nx)) continue;
			auto nc = c
				+ (operation != V[y][x] ? C[operation] : 0);
			if(dist[ny][nx][(d + operation) % 4] > nc) {
				dist[ny][nx][(d + operation) % 4] = nc;
				Q.emplace(nc, ny, nx, (d + operation) % 4);
			}
		}
	}
	long long ans = (long long) (1e18);
	for(int d = 0; d < 4; d++) {
		ans = min(ans, dist[H - 1][W - 1][d]);
	}
	cout << ans << endl;
}

int main() {
	cin >> W >> H;
	while(W != 0) {
		solve();
		cin >> W >> H;
	}
	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3232
final_rank: 1