Problem:
屋台 (Food stalls)
問題
JOI 君の住む IOI 市は，南北方向に H 区画，東西方向に W 区画の長方形の形をしており，H × W 個の区画に区切られている．北から i 番目，西から j 番目の区画を (i, j) と表す．現在，IOI 市で開催されている国際的なプログラミングコンテストを記念して，大規模なお祭りが開催されている．いくつかの区画には屋台が出ており，それぞれ違う種類のお菓子を販売している．
区画 (1, 1), 区画 (H, W) およびそれらに東西南北に隣接する区画には屋台はない．
JOI 君は区画 (1, 1) から区画 (H, W) に移動する．移動時間を短くするため，JOI 君は東あるいは南のみに移動を行う．JOI 君はお菓子が好きなので，区画に入るごとに順に次の行動をとる．
現在の区画にまだ買っていないお菓子を販売している屋台が出ている場合，その屋台でお菓子を購入する．
現在の区画の東西南北に隣接する区画にまだ買っていないお菓子を販売している屋台が出ている場合，それらの屋台のうち 1 つを除く全ての屋台から販売員を呼んで，お菓子を購入する．
JOI 君は同じ種類のお菓子を複数回購入することはない．
IOI 市の大きさ，屋台の位置と，それぞれの屋台のお菓子の値段が与えられたとき，JOI 君が区画 (1, 1) から区画 (H, W) に移動する間に購入するお菓子の総額の最小値を求めよ．
入力
入力は 1 + H 行からなる．
1 行目には，2 つの整数 H, W (3 ≦ H ≦ 1000, 3 ≦ W ≦ 1000) が空白を区切りとして書かれている．これは，IOI 市が H × W 個の区画に区切られていることを表す．
続く H 行にはそれぞれ W 文字からなる文字列が書かれており，IOI 市のそれぞれの区画の情報を表す．H 行のうちの i 行目の左から j 番目の文字 (1 ≦ i ≦ H, 1 ≦ j ≦ W) は，区画 (i, j) に屋台がない場合には '.' (ピリオド) である．屋台がある場合には '1', '2', ..., '9' のいずれかであり，その屋台で販売しているお菓子の値段を表す．
与えられる 5 つの入力データのうち，入力 1 では，屋台のある区画の数は 20 以下である．
出力
JOI 君が区画 (1, 1) から区画 (H, W) に移動する間に購入するお菓子の総額の最小値を 1 行で出力せよ．
入出力例
入力例 1
5 5
..483
.59.9
3.866
79...
4.8..
出力例 1
20
入力例 2
12 10
..498522.4
.633527629
54.4621596
634.213458
1924518685
7739539767
276155.3.6
87716372.2
.858877595
7998739511
3438.5852.
568.9319..
出力例 2
63
入出力例 1 においては，区画 (1, 1)，区画 (2, 1)，区画 (3, 1)，区画 (3, 2)，区画 (4, 2)，区画 (4, 3)，区画 (4, 4)，区画 (4, 5)，区画 (5, 5) の順番に移動して，区画 (3, 1)，区画 (3, 3)，区画 (4, 2) の屋台で販売しているお菓子を購入すると，購入するお菓子の総額が最小となる．
情報オリンピック日本委員会作 『第 15 回日本情報オリンピック JOI 2015/2016 予選競技課題』

Submitted solutions:

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


//到着時の状態
#define Right_North 0
#define North 1
#define Here 2
#define Left 3
#define Left_South 4

//あるマスで調べる状態
#define UE 0
#define HIDARI 1
#define KOKO 2
#define MIGI 3
#define SHITA 4

char input[1000][1001];
int POW[6];
int table[1002][1002];
int min_cost[1002][1002][32];

int H,W;

int main(){

	for(int i = 0; i < 6; i++)POW[i] = pow(2,i);

	scanf("%d %d",&H,&W);

	for(int row = 0; row < H; row++){
		scanf("%s",input[row]);
	}

	//ダミーセルを用意
	for(int col = 0; col <= W+1; col++){
		table[0][col] = 0;
		table[H+1][col] = 0;
	}
	for(int row = 0; row <= H+1; row++){
		table[row][0] = 0;
		table[row][W+1] = 0;
	}

	//マップを転記
	for(int row = 0; row < H; row++){
		for(int col = 0; col < W; col++){
			if(input[row][col] == '.'){
				table[row+1][col+1] = 0;
			}else{
				table[row+1][col+1] = input[row][col]-'0';
			}
		}
	}

	for(int row = 1; row <= H; row++){
		for(int col = 1; col <= W; col++){
			for(int state = 0; state < 32; state++){
				min_cost[row][col][state] = BIG_NUM;
			}
		}
	}

	/*
	 * min_cost[row][col][隣接5箇所の数字を取得したか] = 最小コスト
	 * stateのビット:位置ビットの屋台の菓子を既に食べたか
	 *
	 */
	min_cost[1][1][0] = 0;
	int add_sum,add_loc,removed_add,removed_loc;
	int next_state;
	bool FLG;

	for(int row = 1; row <= H; row++){
		for(int col = 1; col <= W; col++){
			for(int state = 0; state < 32; state++){
				if(min_cost[row][col][state] == BIG_NUM)continue;

				//上下左右+今いる地点で、未加算の数字を調べる
				add_sum = 0,add_loc = 0;

				//上
				if((state & (1 << North)) == 0 && table[row-1][col] != 0){ //上が未加算で、かつ0でない
					add_sum += table[row-1][col];
					add_loc += POW[UE];
				}
				//左
				if((state & (1 << Left)) == 0 && table[row][col-1] != 0){
					add_sum += table[row][col-1];
					add_loc += POW[HIDARI];
				}
				//今いる場所
				if((state & (1 << Here)) == 0 && table[row][col] != 0){
					add_sum += table[row][col];
					add_loc += POW[KOKO];
				}
				//右
				if(table[row][col+1] != 0){
					add_sum += table[row][col+1];
					add_loc += POW[MIGI];
				}
				//下
				if(table[row+1][col] != 0){
					add_sum += table[row+1][col];
					add_loc += POW[SHITA];
				}

				if(add_loc == 0){ //数字を除く必要がない場合

					//右に進む
					next_state = 0;
					if(state & (1 << Right_North)){ //右上→上になる
						next_state += POW[North];
					}
					//今いる場所→左になる
					next_state += POW[Left]; //今いる場所は加算済み、または0、よって右のマスは今のマスを見る必要はない

					//右→「今いる場所になる」
					next_state += POW[Here]; //★add_loc == 0により

					//下は左下になる
					next_state += POW[Left_South]; //★add_loc == 0なので、table[row][col+1]は、新しい左下を無視して良いということ!
					min_cost[row][col+1][next_state] = min(min_cost[row][col+1][next_state],min_cost[row][col][state]);

					//下に進む
					next_state = 0;
					//今いる場所→上になる
					next_state += POW[North];

					if(state & (1 << Left_South)){ //左下→下になる
						next_state += POW[Left];
					}
					//右は右上になる
					next_state += POW[Right_North]; //★add_loc == 0のため
					//下は「今いる場所」になる
					next_state += POW[Here]; //★add_loc == 0のため、無条件で良い

					min_cost[row+1][col][next_state] = min(min_cost[row+1][col][next_state],min_cost[row][col][state]);
					continue;
				}

				//数字を除く必要がある場合

				for(int remove_loc = 0; remove_loc <= 4; remove_loc++){
					if(remove_loc == 2){

						if(add_loc == POW[KOKO]){ //★★今いる場所だけを加算した場合★★

							//右に進む
							next_state = 0;
							if(state & (1 << Right_North)){ //右上→上になる
								next_state += POW[North];
							}
							//今いる場所→左になる
							next_state += POW[Left]; //今いる場所は加算済み、または0、よって右のマスは今のマスを見る必要はない

							//右→「今いる場所になる」
							next_state += POW[Here]; //★add_loc == POW[KOKO]により

							//下は左下になる
							next_state += POW[Left_South]; //★add_loc == POW[KOKO]なので、table[row][col+1]は、新しい左下を無視して良いということ!
							min_cost[row][col+1][next_state] = min(min_cost[row][col+1][next_state],min_cost[row][col][state]+table[row][col]);

							//下に進む
							next_state = 0;
							//今いる場所→上になる
							next_state += POW[North];

							if(state & (1 << Left_South)){ //左下→下になる
								next_state += POW[Left];
							}
							//右は右上になる
							next_state += POW[Right_North]; //★add_loc == POW[KOKO]のため
							//下は「今いる場所」になる
							next_state += POW[Here]; //★add_loc == POW[KOKO]のため、無条件で良い

							min_cost[row+1][col][next_state] = min(min_cost[row+1][col][next_state],min_cost[row][col][state]+table[row][col]);

						}
						continue; //今いる場所は除けない
					}

					FLG = false;

					switch(remove_loc){
					case 0: //上
						if(add_loc & (1 << UE)){
							FLG = true;
							removed_add = add_sum-table[row-1][col];
							removed_loc = UE;
						}
						break;
					case 1: //左
						if(add_loc & (1 << HIDARI)){
							FLG = true;
							removed_add = add_sum-table[row][col-1];
							removed_loc = HIDARI;
						}
						break;
					case 3: //右
						if(add_loc & (1 << MIGI)){
							FLG = true;
							removed_add = add_sum-table[row][col+1];
							removed_loc = MIGI;
						}
						break;
					case 4: //下
						if(add_loc & (1 << SHITA)){
							FLG = true;
							removed_add = add_sum-table[row+1][col];
							removed_loc = SHITA;
						}
						break;
					}
					if(!FLG)continue;

					//右に進む
					next_state = 0;
					if(state & (1 << Right_North)){ //右上→上になる
						next_state += POW[North];
					}
					//今いる場所→左になる
					next_state += POW[Left]; //table[row][col+1]から見れば、仮に左のマスから来たなら、table[row][col]は加算不要なはず(今いるセルは除けないし、0なら無視して良い)

					//右→今いる場所になる
					if(removed_loc != MIGI && (add_loc & (1 << MIGI)) != 0){ //右は除外マスでなく、かつ加算されている
						next_state += POW[Here]; //加算済とする
					}

					//下→左下になる
					if(removed_loc != SHITA && (add_loc & (1 << SHITA)) != 0){ //下は除外マスでなく、かつ加算されている
						next_state += POW[Left_South]; //加算済とする
					}
					min_cost[row][col+1][next_state] = min(min_cost[row][col+1][next_state],min_cost[row][col][state]+removed_add);

					//下に進む
					next_state = 0;
					//今いる場所→上になる
					next_state += POW[North]; //右に進む場合と同様の理由で、無条件で良し

					if(state & (1 << Left_South)){ //左下→下になる
						next_state += POW[Left];
					}
					//右は右上になる
					if(removed_loc != MIGI && (add_loc & (1 << MIGI)) != 0){ //右は除外マスでなく、かつ加算されている
						next_state += POW[Right_North]; //加算済とする
					}
					//下は今いる場所になる
					if(removed_loc != SHITA && (add_loc & (1 << SHITA)) != 0){ //右は除外マスでなく、かつ加算されている
						next_state += POW[Here]; //加算済とする
					}
					min_cost[row+1][col][next_state] = min(min_cost[row+1][col][next_state],min_cost[row][col][state]+removed_add);
				}
			}
		}
	}

	int ans = BIG_NUM;
	for(int state = 0; state < 32; state++){
		ans = min(ans,min_cost[H][W][state]);
	}

	printf("%d\n",ans);

	return 0;
}
accuracy: 1
time_ms: 150
memory_kb: 134232
final_rank: 9

code_snippet: #pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
ll myRand(ll B) { return (ull)rng() % B; }

int dp[2][3][3][1001][1001];

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int h, w;
    cin >> h >> w;
    vector<vector<int>> cost(h + 1, vector<int>(w + 1));
    for (int i = 0; i < h; ++i) {
        for (int j = 0; j < w; ++j) {
            char c;
            cin >> c;
            if (c == '.') continue;
            cost[i][j] = c - '0';
        }
    }
    for (int i = 0; i < 2; ++i) {
        for (int j = 0; j < 3; ++j) {
            for (int k = 0; k < 3; ++k) {
                for (int l = 0; l < h; ++l) {
                    for (int m = 0; m < w; ++m) {
                        dp[i][j][k][l][m] = 1e9;
                    }
                }
            }
        }
    }
    // 0:無し,1:下,2:右)
    dp[0][0][1][0][0] = cost[0][0] + cost[0][1];
    dp[0][0][1][0][0] = cost[0][0] + cost[1][0];
    for (int i = 0; i < h; ++i) {
        for (int j = 0; j < w; ++j) {
            for (int p = 0; p < 2; ++p) {
                for (int q = 0; q < 3; ++q) {
                    for (int r = 0; r < 3; ++r) {
                        int pre = dp[p][q][r][i][j];
                        if (pre == 1e9) continue;
                        if (i + 1 < h) {
                            int nxt = pre;
                            if (r == 1) nxt += cost[i + 1][j];
                            // 左使わない
                            dp[0][r][0][i + 1][j] = min(dp[0][r][0][i + 1][j], nxt + cost[i + 2][j] + cost[i + 1][j + 1]);
                            int add = 0;
                            if (p == 0) {
                                if (j) add = cost[i + 1][j - 1];
                            } else {
                                if (q == 1 and j) add = cost[i + 1][j - 1];
                            }
                            // 下使わない
                            dp[0][r][1][i + 1][j] = min(dp[0][r][1][i + 1][j], nxt + cost[i + 1][j + 1] + add);
                            // 右使わない
                            dp[0][r][2][i + 1][j] = min(dp[0][r][2][i + 1][j], nxt + cost[i + 2][j] + add);
                        }
                        if (j + 1 < w) {
                            int nxt = pre;
                            if (r == 2) nxt += cost[i][j + 1];
                            // 上使わない
                            dp[1][r][0][i][j + 1] = min(dp[1][r][0][i][j + 1], nxt + cost[i][j + 2] + cost[i + 1][j + 1]);
                            int add = 0;
                            if (p == 1) {
                                if (i) add = cost[i - 1][j + 1];
                            } else {
                                if (q == 2 and i) add = cost[i - 1][j + 1];
                            }
                            // 右使わない
                            dp[1][r][2][i][j + 1] = min(dp[1][r][2][i][j + 1], nxt + cost[i + 1][j + 1] + add);
                            // 下使わない
                            dp[1][r][1][i][j + 1] = min(dp[1][r][1][i][j + 1], nxt + cost[i][j + 2] + add);
                        }
                    }
                }
            }
        }
    }
    int res = 1e9;
    for (int i = 0; i < 2; ++i) {
        for (int j = 0; j < 3; ++j) {
            for (int k = 0; k < 3; ++k) {
                res = min(res, dp[i][j][k][h - 1][w - 1]);
            }
        }
    }
    cout << res << endl;
}
accuracy: 1
time_ms: 90
memory_kb: 77188
final_rank: 5

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

//1  2   4   : 7
//8  16  32  : 56 
//64 128 256 : 448

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    int h, w, INF = 1 << 30;
    cin >> h >> w;
    vector<string> A(h);
    vector<int> c = {2, 8, 32, 128};
    vector<pair<int,int>> dir = {{-1, 0}, {0, -1}, {0, 1}, {1, 0}};
    vector<vector<int>> B(h, vector<int>(w)), nxt(w, vector<int>(1 << 9, INF));
    vector<vector<vector<int>>> dp(2, vector<vector<int>>(w, vector<int>(1 << 9, INF)));
    for(auto &&s:A)cin >> s;
    dp[0][0][16] = (A[0][0] == '.' ? '0' : '1') - '0';
    auto f = [&](int s, int y, int x, int S, int fv){
        int v = 0, dy, dx, T = 2 + 16 + 8 + 32 + 128;
        if(y >= h || x >= w)return;
        if(!(S & 16) && A[y][x] != '.')v += A[y][x] - '0';
        for(int i = 0; i < 4; i++){
            tie(dy, dx) = dir[i];
            if(S & c[i])continue;
            if(y + dy < 0 || y + dy >= h || x + dx < 0 || x + dx >= w)continue;
            if(A[y + dy][x + dx] == '.')continue;
            v += A[y + dy][x + dx] - '0';
        }
        dp[s][x][S | T] = min(dp[s][x][S | T], fv + v);
        for(int i = 0; i < 4; i++){
            tie(dy, dx) = dir[i];
            int dec = 0;
            if(S & c[i])continue;
            if(y + dy < 0 || y + dy >= h || x + dx < 0 || x + dx >= w)continue;
            if(A[y + dy][x + dx] != '.')dec = A[y + dy][x + dx] - '0';
            dp[s][x][S | (T ^ c[i])] = min(dp[s][x][S | (T ^ c[i])], fv + v - dec);
        }
    };
    for(int y = 0; y < h; y++){
        dp[1] = nxt;
        for(int x = 0; x < w; x++){
            for(int S = 0; S < (1 << 9); S++){
                if(dp[0][x][S] == INF)continue;
                f(1, y + 1, x, S >> 3, dp[0][x][S]);
                f(0, y, x + 1, (S ^ (S & 1) ^ (S & 8) ^ (S & 64)) >> 1, dp[0][x][S]);
            }
        }
        if(y + 1 != h)swap(dp[0], dp[1]);
    }
    cout << *min_element(dp[0][w - 1].begin(), dp[0][w - 1].end()) << '\n';
}
accuracy: 1
time_ms: 1100
memory_kb: 15048
final_rank: 6

code_snippet: #include <bits/stdc++.h>
using namespace std;
using lint = long long;
#define rep(i, n) for(int i = 0; i < int(n); i++)
#define rep2(i, l, n) for(int i = int(l); i < int(n); i++)

int has(int a, int k){
    return (a >> k) & 1;
}

int h, w;
string s[1010];

bool inside(int y, int x){
    return 0 <= y && y < h && 0 <= x && x < w;
}

int get(int y, int x){
    if(!inside(y, x) || s[y][x] == '.'){
        return -1;
    }else{
        return s[y][x] - '0';
    }
}

int dp[1010][1010][2][2][2][2][2];

int move(int y, int x, bool t, bool u, bool ur, bool l, bool ld){
    if(y > h - 1 || x > w - 1) return 1e9;
    if(y == h - 1 && x == w - 1) return 0;
    if(dp[y][x][t][u][ur][l][ld] != -1){
        return dp[y][x][t][u][ur][l][ld];
    }
    
    int a = get(y, x);
    int ua = get(y - 1, x);
    int la = get(y, x - 1);
    int da = get(y + 1, x);
    int ra = get(y, x + 1);
    
    vector<char> yatai;
    if(ua != -1 && !u) yatai.push_back('u');
    if(la != -1 && !l) yatai.push_back('l');
    if(da != -1) yatai.push_back('d');
    if(ra != -1) yatai.push_back('r');
    
    if(yatai.empty()) yatai.push_back('u');
    
    int ans = 1e9;
    for(char c: yatai){
        int flag = 0, sum = 0;
        for(char d: yatai){
            if(c == d) continue;
            if(d == 'u') flag += (1 << 0), sum += ua;
            if(d == 'l') flag += (1 << 1), sum += la;
            if(d == 'd') flag += (1 << 2), sum += da;
            if(d == 'r') flag += (1 << 3), sum += ra;
        }

        if(a != -1 && !t) sum += a;
        
        // GO DOWN
        do{
            if(y == h - 1) break;
            
            bool t2 = has(flag, 2);
            bool u2 = true;
            bool ur2 = has(flag, 3);
            bool l2 = ld;
            bool ld2 = false;
            
            ans = min(ans, sum + move(y + 1, x, t2, u2, ur2, l2, ld2));
        }while(0);
        
        // GO RIGHT
        do{
            if(x == w - 1) break;
            
            bool t2 = has(flag, 3);
            bool u2 = ur;
            bool ur2 = false;
            bool l2 = true;
            bool ld2 = has(flag, 2);
            
            ans = min(ans, sum + move(y, x + 1, t2, u2, ur2, l2, ld2));
        }while(0);
    }
    
    return dp[y][x][t][u][ur][l][ld] = ans;
}

int main(){
    cin >> h >> w;
    rep(i, h) cin >> s[i];
    
    memset(dp, -1, sizeof(dp));
    int ans1 = move(0, 1, false, false, false, false, false);
    int ans2 = move(1, 0, false, false, false, false, false);
    cout << min(ans1, ans2) << endl;
}
accuracy: 1
time_ms: 720
memory_kb: 133320
final_rank: 12

code_snippet: #include <iostream>
#include <utility>
#include <tuple>
#include <vector>
#include <string>
#include <map>
#include <unordered_map>
#include <set>
#include <unordered_set>
#include <algorithm>
#include <functional>
#include <climits>
#include <numeric>
#include <queue>
#include <cmath>
#include <iomanip>
#include <array>
#include <string>
#include <stack>
#include <cassert>
#include <memory>

template<typename T>
bool contains(const std::vector<T>& list, const T& target) {
	return std::find(list.begin(), list.end(), target) != list.end();
}
template<typename T, int C>
bool contains(const std::array<T, C>& array, const T& target) {
	return std::find(array.begin(), array.end(), target) != array.end();
}
struct Coordinate {
	int x{ 0 }, y{ 0 };
	constexpr Coordinate operator+(const Coordinate& that) const {
		return Coordinate{ x + that.x, y + that.y };
	}
	constexpr bool operator==(const Coordinate& that) const {
		return x == that.x && y == that.y;
	}
	constexpr Coordinate operator-(const Coordinate& that) const {
		return Coordinate{ x - that.x, y - that.y };
	}
	Coordinate& operator+=(const Coordinate& that) {
		x += that.x; y += that.y;
		return *this;
	}
};
constexpr std::array<Coordinate, 4> relative{ Coordinate{1, -1}, Coordinate{1, 0}, Coordinate{0, 1}, Coordinate{-1, 1} };
constexpr std::array<Coordinate, 2> next{ Coordinate{1, 0}, Coordinate{0, 1} };
constexpr std::array<Coordinate, 4> neighbor{ Coordinate{1, 0}, Coordinate{-1, 0}, Coordinate{0, 1}, Coordinate{0, -1} };

struct State {
	int pattern{ 0 };
	std::vector<Coordinate> bought() const {
		std::vector<Coordinate> result;
		for (auto i = 0; i < 4; ++i) {
			if (((1 << i) & pattern) != 0) {
				result.push_back(relative[i]);
			}
		}
		return result;
	}
	State() {}
	State(const Coordinate position, const std::vector<Coordinate>& bought) {
		for (auto i = 0; i < 4; ++i) {
			if (contains(bought, position + relative[i])) {
				pattern += 1 << i;
			}
		}
	}
};
struct Tuple {
	State state;
	Coordinate position;
	int cost;
};
template<typename T>
std::vector<T> operator+(const std::vector<T>& a, const std::vector<T>& b) {
	std::vector<T> result; result.resize(a.size() + b.size());
	for (const auto& v : a) result.push_back(v);
	for (const auto& v : b) result.push_back(v);
	return result;
}
std::vector<Tuple> next_state(const std::vector<std::vector<int>>& map, const Tuple tuple) {
	auto bought = tuple.state.bought(); for (auto& b : bought) b += tuple.position;
	std::vector<Tuple> result;
	for (const auto &dp : next) {
		const auto next = dp + tuple.position;
		if (0 > next.y || next.y >= map.size() || 0 > next.x || next.x >= map[next.y].size()) continue;
		std::vector<Coordinate> shop;
		int cost{ contains(bought, next) ? 0 : map[next.y][next.x] };
		for (const auto &np : neighbor) {
			const auto s = next + np;
			if (0 > s.y || s.y >= map.size() || 0 > s.x || s.x >= map[s.y].size()) continue;
			if (s == tuple.position || map[s.y][s.x] == 0 || contains(bought, s)) continue;
			shop.push_back(s);
			cost += map[s.y][s.x];
		}
		cost += tuple.cost;
		const auto last_state = State(next, bought + shop);
		result.push_back(Tuple{ last_state, next, cost });
		for (const auto np: neighbor) {
			const auto sp = next + np;
			if (!contains(shop, sp)) continue;
			auto ri = std::distance(relative.begin(), std::find(relative.begin(), relative.end(), np));
			auto last = last_state;
			if (ri < 4) {
				last.pattern -= 1 << ri;
			}
			result.push_back(Tuple{ last, next, cost - map[sp.y][sp.x] });
		}
	}
	return result;
}

int main() {
	int height, width; std::cin >> height >> width;
	std::vector<std::vector<int>> map(height, std::vector<int>(width));
	for (auto i = 0; i < height; ++i) {
		std::string str; std::cin >> str;
		for (auto j = 0; j < width; ++j) {
			switch (str[j]) {
			case '.': map[i][j] = 0; break;
			default: map[i][j] = str[j] - '0';
			}
		}
	}
	std::vector<std::vector<std::vector<int>>> min_cost(height, std::vector<std::vector<int>>(width, std::vector<int>(1 << 4, INT_MAX)));
	const auto comparator = [](const Tuple& a, const Tuple& b) {return a.cost > b.cost; };
	std::priority_queue<Tuple, std::vector<Tuple>, decltype(comparator)> queue(comparator);
	min_cost[0][0][0] = 0;
	queue.push(Tuple{ State(), Coordinate(), 0 });
	while (!queue.empty()) {
		auto top = queue.top(); queue.pop();
		if (min_cost[top.position.y][top.position.x][top.state.pattern] != top.cost) continue;
		if (top.position == Coordinate{ width - 1, height - 1 }) break;
		for (auto next : next_state(map, top)) {
			if (min_cost[next.position.y][next.position.x][next.state.pattern] > next.cost) {
				min_cost[next.position.y][next.position.x][next.state.pattern] = next.cost;
				queue.push(next);
			}
		}
	}
	std::cout << *std::min_element(min_cost.back().back().begin(), min_cost.back().back().end()) << std::endl;
}
accuracy: 1
time_ms: 6750
memory_kb: 109572
final_rank: 18

code_snippet: #include <string>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
const int inf = 1012345678;
int A[1006][1006], dp[1006][1006][9];
int main() {
	cin.tie(0);
	ios_base::sync_with_stdio(false);
	int H, W;
	cin >> H >> W;
	for (int i = 0; i < H; ++i) {
		string S;
		cin >> S;
		for (int j = 0; j < W; ++j) {
			if (S[j] != '.') {
				A[i + 1][j + 1] = S[j] - '0';
			}
		}
	}
	for (int i = 1; i <= H; ++i) {
		for (int j = 1; j <= W; ++j) {
			for (int k = 0; k < 9; ++k) {
				dp[i][j][k] = inf;
			}
		}
	}
	dp[1][1][0] = A[0][0] + A[1][0];
	dp[1][1][1] = A[0][0] + A[0][1];
	for (int i = 1; i <= H; ++i) {
		for (int j = 1; j <= W; ++j) {
			if (j < W) {
				dp[i][j + 1][0] = min(dp[i][j + 1][0], A[i + 1][j + 1] + min({ dp[i][j][1] + A[i - 1][j + 1], dp[i][j][4] + A[i - 1][j + 1], dp[i][j][7] }));
				dp[i][j + 1][1] = min(dp[i][j + 1][1], A[i][j + 2] + min({ dp[i][j][1] + A[i - 1][j + 1], dp[i][j][4] + A[i - 1][j + 1] , dp[i][j][7] }));
				dp[i][j + 1][2] = min(dp[i][j + 1][2], A[i][j + 2] + A[i + 1][j + 1] + min({ dp[i][j][1], dp[i][j][4], dp[i][j][7] }));
				dp[i][j + 1][3] = min(dp[i][j + 1][3], A[i + 1][j + 1] + min({ dp[i][j][0] + A[i][j + 1] + A[i - 1][j + 1], dp[i][j][2] + A[i - 1][j + 1], dp[i][j][3] + A[i][j + 1] + A[i - 1][j + 1], dp[i][j][5] + A[i - 1][j + 1], dp[i][j][6] + A[i][j + 1], dp[i][j][8] }));
				dp[i][j + 1][4] = min(dp[i][j + 1][4], A[i][j + 2] + min({ dp[i][j][0] + A[i][j + 1] + A[i - 1][j + 1], dp[i][j][2] + A[i - 1][j + 1], dp[i][j][3] + A[i][j + 1] + A[i - 1][j + 1], dp[i][j][5] + A[i - 1][j + 1], dp[i][j][6] + A[i][j + 1], dp[i][j][8] }));
				dp[i][j + 1][5] = min(dp[i][j + 1][5], A[i][j + 2] + A[i + 1][j + 1] + min({ dp[i][j][0] + A[i][j + 1] , dp[i][j][2], dp[i][j][3] + A[i][j + 1], dp[i][j][5], dp[i][j][6] + A[i][j + 1], dp[i][j][8] }));
			}
			if (i < H) {
				dp[i + 1][j][0] = min(dp[i + 1][j][0], A[i + 2][j] + min({ dp[i][j][0] + A[i + 1][j - 1], dp[i][j][3], dp[i][j][6] + A[i + 1][j - 1] }));
				dp[i + 1][j][1] = min(dp[i + 1][j][1], A[i + 1][j + 1] + min({ dp[i][j][0] + A[i + 1][j - 1], dp[i][j][3], dp[i][j][6] + A[i + 1][j - 1] }));
				dp[i + 1][j][2] = min(dp[i + 1][j][2], A[i + 2][j] + A[i + 1][j + 1] + min({ dp[i][j][0], dp[i][j][3], dp[i][j][6] }));
				dp[i + 1][j][6] = min(dp[i + 1][j][6], A[i + 2][j] + min({ dp[i][j][1] + A[i + 1][j] + A[i + 1][j - 1], dp[i][j][2] + A[i + 1][j - 1], dp[i][j][4] + A[i + 1][j], dp[i][j][5], dp[i][j][7] + A[i + 1][j] + A[i + 1][j - 1], dp[i][j][8] + A[i + 1][j - 1] }));
				dp[i + 1][j][7] = min(dp[i + 1][j][7], A[i + 1][j + 1] + min({ dp[i][j][1] + A[i + 1][j] + A[i + 1][j - 1], dp[i][j][2] + A[i + 1][j - 1], dp[i][j][4] + A[i + 1][j], dp[i][j][5], dp[i][j][7] + A[i + 1][j] + A[i + 1][j - 1], dp[i][j][8] + A[i + 1][j - 1] }));
				dp[i + 1][j][8] = min(dp[i + 1][j][8], A[i + 2][j] + A[i + 1][j + 1] + min({ dp[i][j][1] + A[i + 1][j], dp[i][j][2], dp[i][j][4] + A[i + 1][j], dp[i][j][5], dp[i][j][7] + A[i + 1][j], dp[i][j][8] }));
			}
		}
	}
	int ans = *min_element(dp[H][W], dp[H][W] + 9);
	cout << ans << endl;
	return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 42548
final_rank: 1

code_snippet: #include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <tuple>

template <class T>
using MinHeap = std::priority_queue<T, std::vector<T>, std::greater<T>>;

template <class T>
std::vector<T> vec(int len, T elem) { return std::vector<T>(len, elem); }

constexpr int INF = 1 << 30;

const std::vector<int> dx{0, 1, 0, -1, 0}, dy{1, 0, -1, 0, 0};
const std::vector<int> di{0, 0, 1, 1, 2}, dj{1, 2, 0, 1, 0};

void solve() {
    int h, w;
    std::cin >> h >> w;

    auto cost = vec(h, vec(w, 0));
    for (int x = 0; x < h; ++x) {
        for (int y = 0; y < w; ++y) {
            char c;
            std::cin >> c;
            if (c != '.') cost[x][y] = c - '0';
        }
    }

    auto dist = vec(h, vec(w, vec(1 << 5, INF)));
    dist[0][0][0] = 0;
    MinHeap<std::tuple<int, int, int, int>> que;
    que.emplace(dist[0][0][0], 0, 0, 0);

    auto circ = vec(4, vec(4, false));
    while (!que.empty()) {
        int d, x, y, b;
        std::tie(d, x, y, b) = que.top();
        que.pop();
        if (dist[x][y][b] < d) continue;

        for (int l = 0; l < 5; ++l) {
            int i = di[l], j = dj[l];
            circ[i][j] = ((b >> l) & 1);
        }

        int nd = d;
        if (!circ[1][1] && cost[x][y] > 0) {
            nd += cost[x][y];
            circ[1][1] = true;
        }

        std::vector<int> att;
        for (int k = 0; k < 4; ++k) {
            int pi = dx[k] + 1, pj = dy[k] + 1;
            int px = x + dx[k], py = y + dy[k];

            if (px < 0 || h <= px || py < 0 || w <= py) continue;
            if (circ[pi][pj] || cost[px][py] == 0) continue;
            att.push_back(k);
        }

        for (int p = 0; p <= (int)att.size(); ++p) {
            for (int i = 0; i < (int)att.size(); ++i) {
                if (i == p) continue;

                int k = att[i];
                int ni = dx[k] + 1, nj = dy[k] + 1;
                int nx = x + dx[k], ny = y + dy[k];

                nd += cost[nx][ny];
                circ[ni][nj] = true;
            }

            for (int l = 0; l < 2; ++l) {
                int bi = dx[l], bj = dy[l],
                    nx = x + dx[l], ny = y + dy[l];
                if (nx < 0 || h <= nx || ny < 0 || w <= ny) continue;

                int nb = 0;
                for (int k = 0; k < 5; ++k) {
                    int i = bi + di[k], j = bj + dj[k];
                    nb |= (circ[i][j] << k);
                }

                if (dist[nx][ny][nb] <= nd) continue;
                dist[nx][ny][nb] = nd;
                que.emplace(dist[nx][ny][nb], nx, ny, nb);
            }

            for (int i = 0; i < (int)att.size(); ++i) {
                if (i == p) continue;

                int k = att[i];
                int ni = dx[k] + 1, nj = dy[k] + 1;
                int nx = x + dx[k], ny = y + dy[k];

                nd -= cost[nx][ny];
                circ[ni][nj] = false;
            }
        }
    }

    const auto& last = dist.back().back();
    std::cout << *std::min_element(last.begin(), last.end()) << std::endl;
}

int main() {
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);
    std::ios::sync_with_stdio(false);

    solve();

    return 0;
}
accuracy: 1
time_ms: 4820
memory_kb: 171932
final_rank: 16

code_snippet: #include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <tuple>

template <class T>
using MinHeap = std::priority_queue<T, std::vector<T>, std::greater<T>>;

template <class T>
std::vector<T> vec(int len, T elem) { return std::vector<T>(len, elem); }

constexpr int INF = 1 << 30;

const std::vector<int> dx{0, 1, 0, -1, 0}, dy{1, 0, -1, 0, 0};
const std::vector<int> di{0, 0, 1, 1, 2}, dj{1, 2, 0, 1, 0};

void solve() {
    int h, w;
    std::cin >> h >> w;

    auto cost = vec(h, vec(w, 0));
    for (int x = 0; x < h; ++x) {
        for (int y = 0; y < w; ++y) {
            char c;
            std::cin >> c;
            if (c != '.') cost[x][y] = c - '0';
        }
    }

    auto dist = vec(h, vec(w, vec(1 << 6, INF)));
    dist[0][0][0] = 0;
    MinHeap<std::tuple<int, int, int, int>> que;
    que.emplace(dist[0][0][0], 0, 0, 0);

    auto circ = vec(4, vec(4, false));
    while (!que.empty()) {
        int d, x, y, b;
        std::tie(d, x, y, b) = que.top();
        que.pop();
        if (dist[x][y][b] < d) continue;

        for (int l = 0; l < 5; ++l) {
            int i = di[l], j = dj[l];
            circ[i][j] = ((b >> l) & 1);
        }

        int nd = d;
        if (!circ[1][1] && cost[x][y] > 0) {
            nd += cost[x][y];
            circ[1][1] = true;
        }

        std::vector<int> att;
        for (int k = 0; k < 4; ++k) {
            int pi = dx[k] + 1, pj = dy[k] + 1;
            int px = x + dx[k], py = y + dy[k];

            if (px < 0 || h <= px || py < 0 || w <= py) continue;
            if (circ[pi][pj] || cost[px][py] == 0) continue;
            att.push_back(k);
        }

        for (int p = 0; p <= (int)att.size(); ++p) {
            for (int i = 0; i < (int)att.size(); ++i) {
                if (i == p) continue;

                int k = att[i];
                int ni = dx[k] + 1, nj = dy[k] + 1;
                int nx = x + dx[k], ny = y + dy[k];

                nd += cost[nx][ny];
                circ[ni][nj] = true;
            }

            for (int l = 0; l < 2; ++l) {
                int bi = dx[l], bj = dy[l],
                    nx = x + dx[l], ny = y + dy[l];
                if (nx < 0 || h <= nx || ny < 0 || w <= ny) continue;

                int nb = 0;
                for (int k = 0; k < 5; ++k) {
                    int i = bi + di[k], j = bj + dj[k];
                    nb |= (circ[i][j] << k);
                }

                if (dist[nx][ny][nb] <= nd) continue;
                dist[nx][ny][nb] = nd;
                que.emplace(dist[nx][ny][nb], nx, ny, nb);
            }

            for (int i = 0; i < (int)att.size(); ++i) {
                if (i == p) continue;

                int k = att[i];
                int ni = dx[k] + 1, nj = dy[k] + 1;
                int nx = x + dx[k], ny = y + dy[k];

                nd -= cost[nx][ny];
                circ[ni][nj] = false;
            }
        }
    }

    const auto& last = dist.back().back();
    std::cout << *std::min_element(last.begin(), last.end()) << std::endl;
}

int main() {
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);
    std::ios::sync_with_stdio(false);

    solve();

    return 0;
}
accuracy: 1
time_ms: 4920
memory_kb: 297080
final_rank: 19

code_snippet: #include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <tuple>
#include <bitset>

template <class T>
using MinHeap = std::priority_queue<T, std::vector<T>, std::greater<T>>;

template <class T>
std::vector<T> vec(int len, T elem) { return std::vector<T>(len, elem); }

constexpr int INF = 1 << 30;

const std::vector<int> dx{0, 1, 0, -1, 0}, dy{1, 0, -1, 0, 0};
const std::vector<int> di{0, 0, 0, 1, 1, 2}, dj{0, 1, 2, 0, 1, 0};

void solve() {
    int h, w;
    std::cin >> h >> w;

    auto cost = vec(h, vec(w, 0));
    for (int x = 0; x < h; ++x) {
        for (int y = 0; y < w; ++y) {
            char c;
            std::cin >> c;
            if (c != '.') cost[x][y] = c - '0';
        }
    }

    auto dist = vec(h, vec(w, vec(1 << 6, INF)));
    dist[0][0][0] = 0;
    MinHeap<std::tuple<int, int, int, int>> que;
    que.emplace(dist[0][0][0], 0, 0, 0);

    auto circ = vec(4, vec(4, false));
    while (!que.empty()) {
        int d, x, y, b;
        std::tie(d, x, y, b) = que.top();
        que.pop();
        if (dist[x][y][b] < d) continue;

        for (int l = 0; l < 6; ++l) {
            int i = di[l], j = dj[l];
            circ[i][j] = ((b >> l) & 1);
        }

        int nd = d;
        if (!circ[1][1] && cost[x][y] > 0) {
            nd += cost[x][y];
            circ[1][1] = true;
        }

        std::vector<int> att;
        for (int k = 0; k < 4; ++k) {
            int pi = dx[k] + 1, pj = dy[k] + 1;
            int px = x + dx[k], py = y + dy[k];

            if (px < 0 || h <= px || py < 0 || w <= py) continue;
            if (circ[pi][pj] || cost[px][py] == 0) continue;
            att.push_back(k);
        }

        for (int p = 0; p <= (int)att.size(); ++p) {
            for (int i = 0; i < (int)att.size(); ++i) {
                if (i == p) continue;

                int k = att[i];
                int ni = dx[k] + 1, nj = dy[k] + 1;
                int nx = x + dx[k], ny = y + dy[k];

                nd += cost[nx][ny];
                circ[ni][nj] = true;
            }

            for (int l = 0; l < 2; ++l) {
                int bi = dx[l], bj = dy[l],
                    nx = x + dx[l], ny = y + dy[l];
                if (nx < 0 || h <= nx || ny < 0 || w <= ny) continue;

                int nb = 0;
                for (int k = 0; k < 6; ++k) {
                    int i = bi + di[k], j = bj + dj[k];
                    nb |= (circ[i][j] << k);
                }

                if (dist[nx][ny][nb] <= nd) continue;
                dist[nx][ny][nb] = nd;
                que.emplace(dist[nx][ny][nb], nx, ny, nb);
            }

            for (int i = 0; i < (int)att.size(); ++i) {
                if (i == p) continue;

                int k = att[i];
                int ni = dx[k] + 1, nj = dy[k] + 1;
                int nx = x + dx[k], ny = y + dy[k];

                nd -= cost[nx][ny];
                circ[ni][nj] = false;
            }
        }
    }

    const auto& last = dist.back().back();
    std::cout << *std::min_element(last.begin(), last.end()) << std::endl;
}

int main() {
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);
    std::ios::sync_with_stdio(false);

    solve();

    return 0;
}
accuracy: 1
time_ms: 6100
memory_kb: 297060
final_rank: 20

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
template<class T,class U> using P = pair<T,U>;
template<class T> using vec = vector<T>;
template<class T> using vvec = vector<vec<T>>;

int dp[1002][1002][2][2][2][2];

int main(){
    cin.tie(0);
    ios::sync_with_stdio(false);
    int H,W;
    cin >> H >> W;
    vvec<int> F(H+2,vec<int>(W+2,0));
    for(int i=1;i<=H;i++) for(int j=1;j<=W;j++){
        char c;
        cin >> c;
        if(c!='.') F[i][j] = c-'0';
    }
    const int inf = 1e9;
    for(int i=0;i<=H;i++) for(int j=0;j<=W;j++){
        for(int a=0;a<2;a++) for(int b=0;b<2;b++) for(int c=0;c<2;c++) for(int d=0;d<2;d++) dp[i][j][a][b][c][d] = inf;
    }
    for(int a=0;a<2;a++) for(int b=0;b<2;b++) for(int c=0;c<2;c++) for(int d=0;d<2;d++) dp[1][1][a][b][c][d] = 0;
    for(int i=1;i<=H;i++) for(int j=1;j<=W;j++){
        for(int a=0;a<2;a++) for(int b=0;b<2;b++) for(int c=0;c<2;c++) for(int d=0;d<2;d++){
            //右に
            if(j<W){
                int p = (a? F[i][j+1]:0);
                //上を取らない
                dp[i][j+1][0][1][0][c] = min(dp[i][j+1][0][1][0][c],dp[i][j][a][b][c][d]+p+F[i][j+2]+F[i+1][j+1]);
                //右を取らない
                dp[i][j+1][1][1][0][c] = min(dp[i][j+1][1][1][0][c],dp[i][j][a][b][c][d]+p+(b? F[i-1][j+1]:0)+F[i+1][j+1]);
                //下を取らない
                dp[i][j+1][0][1][1][c] = min(dp[i][j+1][0][1][1][c],dp[i][j][a][b][c][d]+p+(b? F[i-1][j+1]:0)+F[i][j+2]);
            }
            if(i<H){
                int p = (c? F[i+1][j]:0);
                //左を取らない
                dp[i+1][j][0][a][0][1] = min(dp[i+1][j][0][a][0][1],dp[i][j][a][b][c][d]+p+F[i+2][j]+F[i+1][j+1]);
                //右を取らない
                dp[i+1][j][1][a][0][1] = min(dp[i+1][j][1][a][0][1],dp[i][j][a][b][c][d]+p+(d? F[i+1][j-1]:0)+F[i+2][j]);
                //下を取らない
                dp[i+1][j][0][a][1][1] = min(dp[i+1][j][0][a][1][1],dp[i][j][a][b][c][d]+p+(d? F[i+1][j-1]:0)+F[i+1][j+1]);
            }
        }
    }
    int ans = inf;
    for(int a=0;a<2;a++) for(int b=0;b<2;b++) for(int c=0;c<2;c++) for(int d=0;d<2;d++) ans = min(ans,dp[H][W][a][b][c][d]);
    cout << ans << endl;
}
accuracy: 1
time_ms: 140
memory_kb: 69600
final_rank: 4

code_snippet: #include "iostream"
#include "climits"
#include "list"
#include "queue"
#include "stack"
#include "set"
#include "functional"
#include "algorithm"
#include "string"
#include "map"
#include "unordered_map"
#include "unordered_set"
#include "iomanip"
#include "cmath"
#include "random"
#include "bitset"
#include "cstdio"
#include "numeric"
#include "cassert"
#include "functional"

using namespace std;

constexpr long long int MOD = 1000000007;
//const int MOD = 1000000007;
//constexpr int MOD = 998244353;
//constexpr long long int MOD = 998244353;

//const double EPS = 1e-8;

//int N, M, K, H, W, L, R;
long long int N, M, K, H, W, L, R;


int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);

	cin >> H >> W;
	vector<string>s(H);
	for (auto &i : s)cin >> i;
	vector<vector<int>>v(H + 2, vector<int>(W + 2));
	for (int i = 1; i <= H; i++) {
		for (int j = 1; j <= W; j++) {
			if (s[i - 1][j - 1] == '.')continue;
			v[i][j] = s[i - 1][j - 1] - '0';
		}
	}
	int dy[] = { -1,0,1,1 };
	int dx[] = { 1,1,0,-1 };
	s[0] = s.back() = string(W + 2, '.');
	vector<vector<vector<int>>>dp(H + 2, vector<vector<int>>(W + 2, vector<int>(16, MOD)));
	dp[1][1][2] = v[1][1] + v[2][1];
	dp[1][1][4] = v[1][1] + v[1][2];
	for (int i = 1; i <= H; i++) {
		for (int j = 1; j <= W; j++) {
			for (int k = 0; k < 16; k++) {
				if (j < W) {
					int add = 0;
					if ((k >> 1) & 1)add = v[i][j + 1];
					if ((k >> 0) & 1) {
						int nx = 1;
						if ((k >> 2) & 1)nx |= 1 << 3;
						dp[i][j + 1][nx] = min(dp[i][j + 1][nx], dp[i][j][k] + add + v[i][j + 2] + v[i + 1][j + 1]);
						add += v[i - 1][j + 1];
					}
					{
						int nx = 1 << 1;
						nx |= 1 << 0;
						if ((k >> 2) & 1)nx |= 1 << 3;
						dp[i][j + 1][nx] = min(dp[i][j + 1][nx], dp[i][j][k] + add + v[i + 1][j + 1]);
					}
					{
						int nx = 1 << 2;
						nx |= 1 << 0;
						if ((k >> 2) & 1)nx |= 1 << 3;
						dp[i][j + 1][nx] = min(dp[i][j + 1][nx], dp[i][j][k] + add + v[i][j + 2]);
					}
				}
				if (i < H) {
					int add = 0;
					if ((k >> 2) & 1)add = v[i + 1][j];
					if ((k >> 3) & 1) {
						int nx = 1 << 3;
						if ((k >> 1) & 1)nx |= 1 << 0;
						dp[i + 1][j][nx] = min(dp[i + 1][j][nx], dp[i][j][k] + add + v[i + 2][j] + v[i + 1][j + 1]);
						add += v[i + 1][j - 1];
					}
					{
						int nx = 1 << 1;
						nx |= 1 << 3;
						if ((k >> 1) & 1)nx |= 1 << 0;
						dp[i + 1][j][nx] = min(dp[i + 1][j][nx], dp[i][j][k] + add + v[i + 2][j]);
					}
					{
						int nx = 1 << 2;
						nx |= 1 << 3;
						if ((k >> 1) & 1)nx |= 1 << 0;
						dp[i + 1][j][nx] = min(dp[i + 1][j][nx], dp[i][j][k] + add + v[i + 1][j + 1]);
					}
				}
			}
		}
	}
	cout << *min_element(dp[H][W].begin(), dp[H][W].end()) << endl;
}
accuracy: 1
time_ms: 200
memory_kb: 109860
final_rank: 7

code_snippet: #include<iostream>
#include<string>
#include<algorithm>
#include<math.h>
#include<queue>
#include<set>
#include<map>
#include<random>
#include<functional>
#include<utility>

typedef long long ll;

#define rep(i,n) for(int i=0; i<n; i++)
#define pb push_back
#define P pair<int, int>
#define PLI pair<ll, int>
#define PLL pair<ll, ll>
#define VI vector<int>
#define VII vector<VI>

using namespace std;


const int INF = 1e9;
const int mru = 1, mu = 1 << 1, ml = 1 << 2, mld = 1 << 3;

int ToBit(int a, int b, int c, int d) {
	return a + (b << 1) + (c << 2) + (d << 3);
}

int H, W;
int stl[1005][1005], dp[1005][1005][1<<4];
int main() {
	cin >> H >> W;
	rep(i, H) rep(j, W) {
		char c;
		cin >> c;
		stl[i + 1][j + 1] = (c == '.') ? 0 : (c - '0');
	}

	rep(i, H) rep(j, W) rep(k, 1<<4) dp[i+1][j+1][k] = INF;
	dp[1][1][0] = 0;
	for (int i = 1; i <= H; i++) {
		for (int j = 1; j <= W; j++) {
			for (int bit = 0; bit < (1 << 4); bit++) {
				if (dp[i][j][bit] == INF) continue;
				bool isru = bit & mru;
				bool isu = bit & mu;
				bool isl = bit & ml;
				bool isld = bit & mld;

				int vu = (isu ? 0 : stl[i - 1][j]);
				int vl = (isl ? 0 : stl[i][j-1]);
				int vd = stl[i+1][j];
				int vr = stl[i][j+1];

				int nbit, nco;
				if (i < H) {
					nco = vd + vr + vu;
					nbit = ToBit(1, 1, isld, 0);
					dp[i + 1][j][nbit] = min(dp[i + 1][j][nbit], dp[i][j][bit] + nco);

					nco = vd + vr + vl;
					nbit = ToBit(1, 1, isld, 0);
					dp[i + 1][j][nbit] = min(dp[i + 1][j][nbit], dp[i][j][bit] + nco);

					nco = vd + vu + vl;
					nbit = ToBit(0, 1, isld, 0);
					dp[i + 1][j][nbit] = min(dp[i + 1][j][nbit], dp[i][j][bit] + nco);
				}
				if (j < W) {
					nco = vr + vu + vl;
					nbit = ToBit(0, isru, 1, 0);
					dp[i][j+1][nbit] = min(dp[i][j+1][nbit], dp[i][j][bit] + nco);

					nco = vr + vu + vd;
					nbit = ToBit(0, isru, 1, 1);
					dp[i][j + 1][nbit] = min(dp[i][j + 1][nbit], dp[i][j][bit] + nco);

					nco = vr + vl + vd;
					nbit = ToBit(0, isru, 1, 1);
					dp[i][j + 1][nbit] = min(dp[i][j + 1][nbit], dp[i][j][bit] + nco);
				}
			}
		}
	}
	int ans = INF;
	rep(i, 1 << 4) ans = min(ans, dp[H][W][i]);
	cout << ans << endl;

	return 0;
}
accuracy: 1
time_ms: 100
memory_kb: 69828
final_rank: 2

code_snippet: #include<iostream>
#include<string>
#include<algorithm>
#include<math.h>
#include<queue>
#include<set>
#include<map>
#include<random>
#include<functional>
#include<utility>

typedef long long ll;

#define rep(i,n) for(int i=0; i<n; i++)
#define pb push_back
#define P pair<int, int>
#define PLI pair<ll, int>
#define PLL pair<ll, ll>
#define VI vector<int>
#define VII vector<VI>

using namespace std;


const int INF = 1e9;
const int mru = 1, mu = 1 << 1, ml = 1 << 2, mld = 1 << 3;

inline int ToBit(int a, int b, int c, int d) {
	return a + (b << 1) + (c << 2) + (d << 3);
}

int H, W;
int stl[1005][1005], dp[1005][1005][1<<4];
int main() {
	cin >> H >> W;
	rep(i, H) rep(j, W) {
		char c;
		cin >> c;
		stl[i + 1][j + 1] = (c == '.') ? 0 : (c - '0');
	}

	rep(i, H) rep(j, W) rep(k, 1<<4) dp[i+1][j+1][k] = INF;
	dp[1][1][0] = 0;
	for (int i = 1; i <= H; i++) {
		for (int j = 1; j <= W; j++) {
			for (int bit = 0; bit < (1 << 4); bit++) {
				if (dp[i][j][bit] == INF) continue;
				bool isru = bit & mru;
				bool isu = bit & mu;
				bool isl = bit & ml;
				bool isld = bit & mld;

				int vu = (isu ? 0 : stl[i - 1][j]);
				int vl = (isl ? 0 : stl[i][j-1]);
				int vd = stl[i+1][j];
				int vr = stl[i][j+1];

				int nbit, nco;
				if (i < H) {
					nco = vd + vr + vu;
					nbit = ToBit(1, 1, isld, 0);
					dp[i + 1][j][nbit] = min(dp[i + 1][j][nbit], dp[i][j][bit] + nco);

					nco = vd + vr + vl;
					nbit = ToBit(1, 1, isld, 0);
					dp[i + 1][j][nbit] = min(dp[i + 1][j][nbit], dp[i][j][bit] + nco);

					nco = vd + vu + vl;
					nbit = ToBit(0, 1, isld, 0);
					dp[i + 1][j][nbit] = min(dp[i + 1][j][nbit], dp[i][j][bit] + nco);
				}
				if (j < W) {
					nco = vr + vu + vl;
					nbit = ToBit(0, isru, 1, 0);
					dp[i][j+1][nbit] = min(dp[i][j+1][nbit], dp[i][j][bit] + nco);

					nco = vr + vu + vd;
					nbit = ToBit(0, isru, 1, 1);
					dp[i][j + 1][nbit] = min(dp[i][j + 1][nbit], dp[i][j][bit] + nco);

					nco = vr + vl + vd;
					nbit = ToBit(0, isru, 1, 1);
					dp[i][j + 1][nbit] = min(dp[i][j + 1][nbit], dp[i][j][bit] + nco);
				}
			}
		}
	}
	int ans = INF;
	rep(i, 1 << 4) ans = min(ans, dp[H][W][i]);
	cout << ans << endl;

	return 0;
}
accuracy: 1
time_ms: 110
memory_kb: 69808
final_rank: 3

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

#define FOR(i,a,b) for(int i= (a); i<((int)b); ++i)
#define RFOR(i,a) for(int i=(a); i >= 0; --i)
#define FOE(i,a) for(auto i : a)
#define ALL(c) (c).begin(), (c).end()
#define RALL(c) (c).rbegin(), (c).rend()
#define SUM(x) std::accumulate(ALL(x), 0LL)
#define MIN(v) *std::min_element(v.begin(), v.end())
#define MAX(v) *std::max_element(v.begin(), v.end())
#define EXIST(v,x) (std::find(v.begin(), v.end(), x) != v.end())
#define BIT_ON(bit, i) (((bit >> i) & 1) > 0)
#define BIT_COUNT(bit) (__builtin_popcount(bit))

typedef long long LL;
template<typename T> std::vector<T> make_v(size_t a){return std::vector<T>(a);}
template<typename T,typename... Ts> auto make_v(size_t a, Ts... ts){ return std::vector<decltype(make_v<T>(ts...))>(a,make_v<T>(ts...));}    // C++14
template<typename T,typename V> typename std::enable_if<std::is_class<T>::value==0>::type fill_v(T &t,const V &v){t=v;}
template<typename T,typename V> typename std::enable_if<std::is_class<T>::value!=0>::type fill_v(T &t,const V &v){for(auto &e:t) fill_v(e,v);}
template<class T> inline T ceil(T a, T b) { return (a + b - 1) / b; }
template<class T> inline void print(T x) { std::cout << x << std::endl; }
template<class T> inline void print_vec(const std::vector<T> &v) { for (int i = 0; i < v.size(); ++i) {  if (i != 0) {std::cout << " ";} std::cout << v[i];} std::cout << "\n"; }
inline bool inside(long long y, long long x, long long H, long long W) {return 0 <= y and y < H and 0 <= x and x < W; }
template<class T> inline double euclidean_distance(T y1, T x1, T y2, T x2) { return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)); }
template<class T> inline double manhattan_distance(T y1, T x1, T y2, T x2) { return abs(x1 - x2) + abs(y1 - y2); }
template<typename T> T &chmin(T &a, const T &b) { return a = std::min(a, b); }
template<typename T> T &chmax(T &a, const T &b) { return a = std::max(a, b); }

template<class T> inline std::vector<T> unique(std::vector<T> v) {
    sort(v.begin(), v.end());
    v.erase(unique(v.begin(), v.end()), v.end());
    return v;
}
// 初項s, 交差dのn個の数列の和
long long sum_of_arithmetic_progression(long long s, long long d, long long n) {
    return n * (2 * s + (n - 1) * d) / 2;
}

// 2のべき乗数かどうか
bool is_power_of_two(long long x) {
    return !(x & (x - 1));
}

// aとbの最大公約数 O(log min(a, b))
long long gcd(long long a, long long b) {
    if (b == 0) { return a; }
    return gcd(b, a % b);
}

// 数列vの最大公約数 O(N log d)
long long gcd(std::vector<long long> &v) {
    long long ans = v[0];
    for (int i = 1; i < (int)v.size(); ++i) {
        ans = gcd(ans, v[i]);
    }
    return ans;
}

// aとbの最小公倍数 O(log min(a, b))
long long lcm(long long a, long long b) {
    long long g = gcd(a, b);
    return a / g * b;
}

const int INF = 1u << 30u;
const long long LINF = 1ull << 58u;
const double EPS = 1e-9;
const long double PI = acos(-1.0);
const std::vector<int> dy2 = {0, 1}, dx2 = {1, 0};  // 右，下
const std::vector<int> dy4 = {0, 1, 0, -1}, dx4 = {1, 0, -1, 0};    // 右，下，左，上
const std::vector<int> dy8 = { 0, -1, 0, 1, 1, -1, -1, 1 }, dx8 = { 1, 0, -1, 0, 1, 1, -1, -1 };

using namespace std;

class Grid {
public:
    const int H;
    const int W;
    const int SPACE = 0;
    const int BLOCK = 1;

    std::vector<std::vector<int>> grid;

    Grid(int h, int w) : H(h), W(w) {
        this->grid.resize(this->H, std::vector<int>(this->W, this->SPACE));
    }

    void set(int y, int x, int s) {
        this->grid[y][x] = s;
    }
};

int bc[] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);

    LL H, W;
    cin >> H >> W;
    Grid grid(H + 10, W + 10);

    FOR(y, 0, H) {
        FOR(x, 0, W) {
            char c;
            cin >> c;
            if (c == '.') {
                grid.set(y + 1, x + 1, 0);
            }
            else {
                grid.set(y + 1, x + 1, c - '0');
            }
        }
    }

    auto dp = make_v<LL>(H + 10, W + 10, 1 << 4);
    fill_v(dp, INF);

    dp[1][1][15] = 0;
    FOR(i, 1, H + 1) {
        FOR(j, 1, W + 1) {
            FOR(state, 0, 1 << 4) {
                // down
                FOR(new_state, 0, 1 << 4) {
                    if (((state & 4) == 0) != ((new_state & 8) == 0)) {
                        continue;
                    }
                    if (not (state & 2)) {
                        continue;
                    }
                    if (bc[state & 1] + bc[new_state & 6] <= 1) {
                        continue;
                    }

                    LL cost = dp[i][j][state];
                    if (new_state & 1) cost += grid.grid[i + 2][j - 1]; // 左下
                    if (new_state & 2) cost += grid.grid[i + 2][j];     // 下
                    if (new_state & 4) cost += grid.grid[i + 1][j + 1]; // 右

                    chmin(dp[i + 1][j][new_state], cost);
                }

                // right
                FOR(new_state, 0, 16) {
                    if (((state & 2) == 0) != ((new_state & 1) == 0)) {
                        continue;
                    }
                    if (!(state & 4)) {
                        continue;
                    }
                    if (bc[state & 8] + bc[new_state & 6] <= 1) {
                        continue;
                    }

                    LL cost = dp[i][j][state];
                    if (new_state & 8) cost += grid.grid[i - 1][j + 2];
                    if (new_state & 4) cost += grid.grid[i][j + 2];
                    if (new_state & 2) cost += grid.grid[i + 1][j + 1];

                    chmin(dp[i][j + 1][new_state], cost);
                }
            }
        }
    }

    print(dp[H][W][15]);

    return 0;
}
accuracy: 1
time_ms: 610
memory_kb: 174588
final_rank: 13

code_snippet: #include<bits/stdc++.h>
using namespace std;
using Int = long long;
template<typename T1,typename T2> inline void chmin(T1 &a,T2 b){if(a>b) a=b;}
template<typename T1,typename T2> inline void chmax(T1 &a,T2 b){if(a<b) a=b;}

//INSERT ABOVE HERE
const int MAX = 1010;
const int INF = MAX * MAX * 10;
int dp[2][4][4][MAX][MAX]={};
int ts[MAX][MAX]={};

signed main(){
  int h,w;
  cin>>h>>w;
  vector<string> vs(h);
  for(int i=0;i<h;i++) cin>>vs[i],vs[i]=".."+vs[i]+"..";
  vs.emplace(vs.begin(),string(w+4,'.'));
  vs.emplace(vs.begin(),string(w+4,'.'));
  vs.emplace_back(string(w+4,'.'));
  vs.emplace_back(string(w+4,'.'));
    
  for(int i=0;i<MAX;i++)
    for(int j=0;j<MAX;j++)
      for(int pp=0;pp<2;pp++)
        for(int pd=0;pd<4;pd++)
          for(int cd=0;cd<4;cd++)
            dp[pp][pd][cd][i][j]=INF;

  for(int pp=0;pp<2;pp++)
    for(int pd=0;pd<4;pd++)
      for(int cd=0;cd<4;cd++)
        dp[pp][pd][cd][2][2]=0;

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

  for(int i=2;i<=h+1;i++){
    for(int j=2;j<=w+1;j++){
      int cy=i,cx=j;
      for(int pp=0;pp<2;pp++){
        int py=cy-dy[pp],px=cx-dx[pp];
        for(int pd=0;pd<4;pd++){
          for(int cd=0;cd<4;cd++){
            cnt++;
            ts[py][px]=ts[cy][cx]=cnt;
            for(int k=0;k<4;k++){
              if(pd!=k) ts[py+dy[k]][px+dx[k]]=cnt;
              if(cd!=k) ts[cy+dy[k]][cx+dx[k]]=cnt;
            }
            int dist=dp[pp][pd][cd][cy][cx];
            for(int npp=0;npp<2;npp++){              
              int npd=cd,ncy=cy+dy[npp],ncx=cx+dx[npp];              
              if(ts[ncy][ncx]!=cnt) continue;
              int sum=0;
              int tmp[4]={};
              for(int k=0;k<4;k++){
                int ty=ncy+dy[k],tx=ncx+dx[k];
                if(ts[ty][tx]!=cnt&&isdigit(vs[ty][tx]))
                  tmp[k]=vs[ty][tx]-'0';
                sum+=tmp[k];                
              }
              for(int ncd=0;ncd<4;ncd++){
                int ndist=dist+sum-tmp[ncd];
                chmin(dp[npp][npd][ncd][ncy][ncx],ndist);                
              }
            }
          }
        }
      }      
    }    
  }
  
  int ans=INF;  
  for(int pp=0;pp<2;pp++)
    for(int pd=0;pd<4;pd++)
      for(int cd=0;cd<4;cd++)
        chmin(ans,dp[pp][pd][cd][h+1][w+1]);  
  cout<<ans<<endl;
  return 0;
}
accuracy: 1
time_ms: 1190
memory_kb: 136428
final_rank: 14

code_snippet: #include <iostream>
#include <fstream>
#include <stdio.h>
#include <math.h>
#include <time.h>
#include <string>
#include <tuple>
#include <vector>
#include <map>
#include <unordered_map>
#include <list>
#include <set>
#include <stack>
#include <queue>
#include <cstdlib>
#include <algorithm>
#include <random>
#include <cassert>
using namespace std;
#define LL long long
#define MP(a, b) make_pair(a, b)
#define POWER9 1000000000
#define MOD POWER9+7
#undef INT_MIN
#undef INT_MAX
#define INT_MIN -2147483647
#define INT_MAX 2147483647
#define LL_MIN (LL)-9223372036854775807
#define LL_MAX (LL)9223372036854775807
#define PI 3.14159265359

int H,W;
int mp[1000][1000];
int cost[1000][1000][32];

int main(){
    cin.tie(0);
    ios::sync_with_stdio(false);

    cin >> H >> W;
    for(int i=0; i<H; i++){
        for(int j=0; j<W; j++){
            char c;
            cin >> c;
            if(c == '.') mp[i][j] = 0;
            else mp[i][j] = c - '0';
            for(int k=0; k<32; k++) cost[i][j][k] = INT_MAX;
        }
    }
    cost[0][0][0] = 0;

    priority_queue<pair<int,pair<pair<int,int>,int> > > que;
    que.push(MP(INT_MAX, MP(MP(0,0), 0)));
    while(!que.empty()){
        int c = INT_MAX-que.top().first;
        int y = que.top().second.first.first;
        int x = que.top().second.first.second;
        int s = que.top().second.second;
        que.pop();
        if(cost[y][x][s] < c) continue;
        if(y==H-1 && x==W-1){
            cout << c << endl;
            return 0;
        }
        int d[5];
        for(int i=0; i<5; i++){
            d[i] = (s>>(4-i)) % 2;
        }

        int nc = 0;
        if(d[0] == 0) nc += mp[y][x];
        if(d[2] == 0 && y-1 >= 0) nc += mp[y-1][x];
        if(d[3] == 0 && x-1 >= 0) nc += mp[y][x-1];
        if(y+1 < H) nc += mp[y+1][x];
        if(x+1 < W) nc += mp[y][x+1];

        int tmpY = (d[4]==1 ? 2 : 0);
        int tmpX = (d[1]==1 ? 4 : 0);
        if(d[2] == 0 && y-1 >= 0){
            nc -= mp[y-1][x];
            if(y+1 < H && cost[y+1][x][16+8+4+tmpY] > c+nc){
                cost[y+1][x][16+8+4+tmpY] = c+nc;
                que.push(MP(INT_MAX-c-nc, MP(MP(y+1, x), 16+8+4+tmpY)));
            }
            if(x+1 < W && cost[y][x+1][16+2+1+tmpX] > c+nc){
                cost[y][x+1][16+2+1+tmpX] = c+nc;
                que.push(MP(INT_MAX-c-nc, MP(MP(y, x+1), 16+2+1+tmpX)));
            }
            nc += mp[y-1][x];
        }
        if(d[3] == 0 && x-1 >= 0){
            nc -= mp[y][x-1];
            if(y+1 < H && cost[y+1][x][16+8+4+tmpY] > c+nc){
                cost[y+1][x][16+8+4+tmpY] = c+nc;
                que.push(MP(INT_MAX-c-nc, MP(MP(y+1, x), 16+8+4+tmpY)));
            }
            if(x+1 < W && cost[y][x+1][16+2+1+tmpX] > c+nc){
                cost[y][x+1][16+2+1+tmpX] = c+nc;
                que.push(MP(INT_MAX-c-nc, MP(MP(y, x+1), 16+2+1+tmpX)));
            }
            nc += mp[y][x-1];
        }
        if(y+1 < H){
            nc -= mp[y+1][x];
            if(y+1 < H && cost[y+1][x][8+4+tmpY] > c+nc){
                cost[y+1][x][8+4+tmpY] = c+nc;
                que.push(MP(INT_MAX-c-nc, MP(MP(y+1, x), 8+4+tmpY)));
            }
            if(x+1 < W && cost[y][x+1][16+2+tmpX] > c+nc){
                cost[y][x+1][16+2+tmpX] = c+nc;
                que.push(MP(INT_MAX-c-nc, MP(MP(y, x+1), 16+2+tmpX)));
            }
            nc += mp[y+1][x];
        }
        if(x+1 < W){
            nc -= mp[y][x+1];
            if(y+1 < H && cost[y+1][x][16+4+tmpY] > c+nc){
                cost[y+1][x][16+4+tmpY] = c+nc;
                que.push(MP(INT_MAX-c-nc, MP(MP(y+1, x), 16+4+tmpY)));
            }
            if(x+1 < W && cost[y][x+1][2+1+tmpX] > c+nc){
                cost[y][x+1][2+1+tmpX] = c+nc;
                que.push(MP(INT_MAX-c-nc, MP(MP(y, x+1), 2+1+tmpX)));
            }
            nc += mp[y][x+1];
        }
    }

    return 0;
}
accuracy: 1
time_ms: 2690
memory_kb: 132796
final_rank: 15

code_snippet: //Food Stalls
#include <iostream>
#include <climits>
#include <vector>

using namespace std;
static const int MAX = 1000;

int H, W;
int A[MAX + 2][MAX + 2], min_cost[MAX + 1][MAX + 1][16];
//(i - 1, j + 1), (i, j + 1), (i + 1. j), (i + 1, j - 1)

enum {
    SOUTHWEST = 0,
    SOUTH = 1,
    EAST = 2,
    NORTHEAST = 3,
    NORTH = 4,
    WEST = 5
};

int main() {
    cin >> H >> W;

    for(int i = 0; i < H + 2; i++) {
        A[i][0] = 0;
        A[i][W + 1] = 0;
    }
    for(int j = 0; j < W + 2; j++) {
        A[0][j] = 0;
        A[H + 1][j] = 0;
    }

    char c;
    for(int i = 1; i < H + 1; i++) {
        for(int j = 1; j < W + 1; j++) {
            cin >> c;
            if(c == '.') A[i][j] = 0;
            else A[i][j] = c - '0';
        }
    }

    for(int i = 1; i < H + 1; i++) {
        for(int j = 1; j < W + 1; j++) {
            for(int k = 0; k < 16; k++) min_cost[i][j][k] = INT_MAX;
        }
    }
    min_cost[1][1][0] = 0;

    for(int i = 1; i < H + 1; i++) {
        for(int j = 1; j < W + 1; j++) {
            for(int k = 0; k < 16; k++) {
                if(min_cost[i][j][k] == INT_MAX) continue;
                int next_cost, next_state;
                vector<int> v;
                //go EAST
                if(j != W) {
                    next_state = ((k & 1 << SOUTH) ? (1 << SOUTHWEST) : 0);
                    next_cost = (k & 1 << EAST) ? min_cost[i][j][k] : min_cost[i][j][k] + A[i][j + 1];
                    if(A[i - 1][j + 1] != 0 && !(k & 1 << NORTHEAST)) {
                        next_cost += A[i - 1][j + 1];
                        v.push_back(NORTH);
                    }
                    if(A[i][j + 2] != 0) {
                        next_cost += A[i][j + 2];
                        v.push_back(EAST);
                        next_state += (1 << EAST);
                    }
                    if(A[i + 1][j + 1] != 0) {
                        next_cost += A[i + 1][j + 1];
                        v.push_back(SOUTH);
                        next_state += (1 << SOUTH);
                    }
                    if(v.size() > 1) {
                        for(auto l: v) {
                            if(l == NORTH) min_cost[i][j + 1][next_state] = min(min_cost[i][j + 1][next_state], next_cost - A[i - 1][j + 1]);
                            else if(l == EAST) min_cost[i][j + 1][next_state - (1 << EAST)] = min(min_cost[i][j + 1][next_state - (1 << EAST)], next_cost - A[i][j + 2]);
                            else min_cost[i][j + 1][next_state - (1 << SOUTH)] = min(min_cost[i][j + 1][next_state - (1 << SOUTH)], next_cost - A[i + 1][j + 1]);
                        }
                    } else {
                        min_cost[i][j + 1][((k & 1 << SOUTH) ? (1 << SOUTHWEST) : 0)] =
                                min(min_cost[i][j + 1][((k & 1 << SOUTH) ? (1 << SOUTHWEST) : 0)],
                                    ((k & 1 << EAST) ? min_cost[i][j][k] : min_cost[i][j][k] + A[i][j + 1]));
                    }
                }
                //go SOUTH
                if(i != H) {
                    v.clear();
                    next_state = ((k & 1 << EAST) ? (1 << NORTHEAST) : 0);
                    next_cost = (k & 1 << SOUTH) ? min_cost[i][j][k] : min_cost[i][j][k] + A[i + 1][j];
                    if(A[i + 1][j - 1] != 0 && !(k & 1 << SOUTHWEST)) {
                        next_cost += A[i + 1][j - 1];
                        v.push_back(WEST);
                    }
                    if(A[i + 2][j] != 0) {
                        next_cost += A[i + 2][j];
                        v.push_back(SOUTH);
                        next_state += (1 << SOUTH);
                    }
                    if(A[i + 1][j + 1] != 0) {
                        next_cost += A[i + 1][j + 1];
                        v.push_back(EAST);
                        next_state += (1 << EAST);
                    }
                    if(v.size() > 1) {
                        for(auto l: v) {
                            if(l == WEST) min_cost[i + 1][j][next_state] = min(min_cost[i + 1][j][next_state], next_cost - A[i + 1][j - 1]);
                            else if(l == SOUTH) min_cost[i + 1][j][next_state - (1 << SOUTH)] = min(min_cost[i + 1][j][next_state - (1 << SOUTH)], next_cost - A[i + 2][j]);
                            else min_cost[i + 1][j][next_state - (1 << EAST)] = min(min_cost[i + 1][j][next_state - (1 << EAST)], next_cost - A[i + 1][j + 1]);
                        }
                    } else {
                        min_cost[i + 1][j][((k & 1 << EAST) ? (1 << NORTHEAST) : 0)] =
                                min(min_cost[i + 1][j][((k & 1 << EAST) ? (1 << NORTHEAST) : 0)],
                                    (k & 1 << SOUTH) ? min_cost[i][j][k] : min_cost[i][j][k] + A[i + 1][j]);
                    }
                }
            }
        }
    }

    cout << min_cost[H][W][0] << endl;

    return 0;
}
accuracy: 1
time_ms: 770
memory_kb: 69588
final_rank: 8

code_snippet: #include <bits/stdc++.h>
                                        #include<iostream>
                                        #include<cstdio>
                                        #include<vector>
                                        #include<queue>
                                        #include<map>
                                        #include<cstring>
                                        #include<string>
                                        #include <math.h>
                                        #include<algorithm>
                                    //    #include <boost/multiprecision/cpp_int.hpp>
                                        #include<functional>
                        //       #define int long long
                                        #define inf  1000000007
                                        #define pa pair<int,int>
                                        #define ll long long
                                        #define pal pair<double,double>
                                        #define ppap pair<pa,int>
                                  
                                        #define ssa pair<string,int>
                                        #define  mp make_pair
                                        #define  pb push_back
                                        #define EPS (1e-7)
                                        #define equals(a,b) (fabs((a)-(b))<EPS)
int dx[4]={0,-1,0,1};
int dy[4]={1,0,-1,0};
                                        using namespace std;
                               			class pa3{
                                        	public:
                                        	int x,y,z;
                                        	pa3(int x=0,int y=0,int z=0):x(x),y(y),z(z) {}
                                        	bool operator < (const pa3 &p) const{
                                        		if(x!=p.x) return x<p.x;
                                        		if(y!=p.y) return y<p.y;
                                        		 return z<p.z;
                                        		//return x != p.x ? x<p.x: y<p.y;
                                        	}
                               				bool operator > (const pa3 &p) const{
                                        		if(x!=p.x) return x>p.x;
                                        		if(y!=p.y) return y>p.y;
                                        		 return z>p.z;
                                        		//return x != p.x ? x<p.x: y<p.y;
                                        	}
                                        	bool operator == (const pa3 &p) const{
                                        		return x==p.x && y==p.y && z==p.z;
                                        	}
                                        		bool operator != (const pa3 &p) const{
                                        			return !( x==p.x && y==p.y && z==p.z);
                                        	}
                                        
                                        };
                                        
                                        class pa4{
                                        	public:
                                        	int x;
                                        	int y,z,w;
                                        	pa4(int x=0,int y=0,int z=0,int w=0):x(x),y(y),z(z),w(w) {}
                                        	bool operator < (const pa4 &p) const{
                                        		if(x!=p.x) return x<p.x;
                                        		if(y!=p.y) return y<p.y;
                                        		if(z!=p.z)return z<p.z;
                                        		return w<p.w;
                                        		//return x != p.x ? x<p.x: y<p.y;
                                        	}
                                        	bool operator > (const pa4 &p) const{
                                        		if(x!=p.x) return x>p.x;
                                        		if(y!=p.y) return y>p.y;
                                        		if(z!=p.z)return z>p.z;
                                        		return w>p.w;
                                        		//return x != p.x ? x<p.x: y<p.y;
                                        	}
                                        	bool operator == (const pa4 &p) const{
                                        		return x==p.x && y==p.y && z==p.z &&w==p.w;
                                        	}
                                        		
                                        
                                        };
                                        class pa2{
                                        	public:
                                        	int x,y;
                                        	pa2(int x=0,int y=0):x(x),y(y) {}
                                        	pa2 operator + (pa2 p) {return pa2(x+p.x,y+p.y);}
                                        	pa2 operator - (pa2 p) {return pa2(x-p.x,y-p.y);}
                                        	bool operator < (const pa2 &p) const{
                                        		return x != p.x ? x<p.x: y<p.y;
                                        	}
                                        	bool operator > (const pa2 &p) const{
                                        		return x != p.x ? x>p.x: y>p.y;
                                        	}
                                        	bool operator == (const pa2 &p) const{
                                        		return abs(x-p.x)==0 && abs(y-p.y)==0;
                                        	}
                                        	bool operator != (const pa2 &p) const{
                                        		return !(abs(x-p.x)==0 && abs(y-p.y)==0);
                                        	}
                                        		
                                        
                                        };
                                        
                                               #define ppa pair<int,pas>
                                        class Point{
                                        	public:
                                        	double x,y;
                                        	Point(double x=0,double y=0):x(x),y(y) {}
                                        	Point operator + (Point p) {return Point(x+p.x,y+p.y);}
                                        	Point operator - (Point p) {return Point(x-p.x,y-p.y);}
                                        	Point operator * (double a) {return Point(x*a,y*a);}
                                        	Point operator / (double a) {return Point(x/a,y/a);}
                                        	double absv() {return sqrt(norm());}
                                        	double norm() {return x*x+y*y;}
                                        	bool operator < (const Point &p) const{
                                        		return x != p.x ? x<p.x: y<p.y;
                                        	}
                                        	bool operator == (const Point &p) const{
                                        		return fabs(x-p.x)<EPS && fabs(y-p.y)<EPS;
                                        	}
                                        };
                                        typedef Point Vector;
                                 #define pl pair<int,pas>
                                        struct Segment{
                                        Point p1,p2;
                                        };
                                         double dot(Vector a,Vector b){
                                        	return a.x*b.x+a.y*b.y;
                                        }
                                        double cross(Vector a,Vector b){
                                        	return a.x*b.y-a.y*b.x;
                                        }
                                    
            bool parareru(Point a,Point b,Point c,Point d){
            //	if(abs(cross(a-b,d-c))<EPS)cout<<"dd "<<cross(a-b,d-c)<<endl;
            	return abs(cross(a-b,d-c))<EPS;
            }
            double distance_ls_p(Point a, Point b, Point c) {
              if ( dot(b-a, c-a) < EPS ) return (c-a).absv();
              if ( dot(a-b, c-b) < EPS ) return (c-b).absv();
              return abs(cross(b-a, c-a)) / (b-a).absv();
            }
            bool is_intersected_ls(Segment a,Segment b) {
            	if(a.p1==b.p1||a.p2==b.p1||a.p1==b.p2||a.p2==b.p2) return false;
            	if(parareru((a.p2),(a.p1),(a.p1),(b.p2))&&parareru((a.p2),(a.p1),(a.p1),(b.p1))){
            //		cout<<"sss"<<endl;
            		if(dot(a.p1-b.p1,a.p1-b.p2)<EPS) return true;
            		if(dot(a.p2-b.p1,a.p2-b.p2)<EPS) return true;
            		if(dot(a.p1-b.p1,a.p2-b.p1)<EPS) return true;
            		if(dot(a.p1-b.p2,a.p2-b.p2)<EPS) return true;
            		return false;
            	}
              else return ( cross(a.p2-a.p1, b.p1-a.p1) * cross(a.p2-a.p1, b.p2-a.p1) < EPS ) && ( cross(b.p2-b.p1, a.p1-b.p1) * cross(b.p2-b.p1, a.p2-b.p1) < EPS );
            }
             
            double segment_dis(Segment a,Segment b){
            	if(is_intersected_ls(a,b))return 0;
            	double r=distance_ls_p(a.p1, a.p2, b.p1);
            	r=min(r,distance_ls_p(a.p1, a.p2, b.p2));
            	r=min(r,distance_ls_p(b.p1, b.p2, a.p2));
            	r=min(r,distance_ls_p(b.p1, b.p2, a.p1));
            	return r;
            }
            Point intersection_ls(Segment a, Segment b) {
              Point ba = b.p2-b.p1;
              double d1 = abs(cross(ba, a.p1-b.p1));
              double d2 = abs(cross(ba, a.p2-b.p1));
              double t = d1 / (d1 + d2);
             
              return a.p1 + (a.p2-a.p1) * t;
            }
             
                            string itos( int i ) {
                            ostringstream s ;
                            s << i ;
                            return s.str() ;
                            }
                             
                            int gcd(int v,int b){
                            	if(v>b) return gcd(b,v);
                            	if(v==b) return b;
                            	if(b%v==0) return v;
                            	return gcd(v,b%v);
                            }
             
                            double distans(double x1,double y1,double x2,double y2){
                            	double rr=(x1-x2)*(x1-x2)+(y1-y2)*(y1-y2);
                            	return sqrt(rr);
                            	
                            }
                            
   //         int pr[2000010];
     //       int inv[2000010];
            
            int beki(int wa,int rr,int warukazu){
            	if(rr==0) return 1ll;
            	if(rr==1) return wa%warukazu;
            	if(rr%2==1) return (beki(wa,rr-1,warukazu)*wa)%warukazu;
            	int zx=beki(wa,rr/2,warukazu);
            	return (zx*zx)%warukazu;
            }
            /*
			int comb(int nn,int rr){
				int r=pr[nn]*inv[rr];
				r%=inf;
				r*=inv[nn-rr];
				r%=inf;
				return r;
			}
            
            void gya(int ert){
            	pr[0]=1;
            	for(int i=1;i<ert;i++){
            		pr[i]=(pr[i-1]*i)%inf;
            	}
            	for(int i=0;i<ert;i++) inv[i]=beki(pr[i],inf-2,inf);
            	
            }
             */
			//priority_queue<pa3,vector<pa3>,greater<pa3>> pq;            
             //sort(ve.begin(),ve.end(),greater<int>());
                                     //----------------kokomade tenpure------------
unsigned int randxor()
{
    static unsigned int x=123456789,y=362436069,z=521288629,w=88675123;
    unsigned int t;
    t=(x^(x<<11));x=y;y=z;z=w; return( w=(w^(w>>19))^(t^(t>>8)) );
}

int mask=(1<<8)-1;
int ban[1010][1010]={0};
map<int,int> ma[2][1010];
  signed main(){
  	              cin.tie(0);
    		ios::sync_with_stdio(false);

  	int n,m;
  	cin>>n>>m;
  	
  	for(int i=1;i<=n;i++){
  		string s;
  		
  		cin>>s;
  		s="2"+s;
  		for(int j=1;j<=m;j++)if(s[j]!='.')ban[i][j]=s[j]-'0';
  	}

  	ma[1][1][ban[2][2]?1:0]=0;
  	  	
  	for(int i=1;i<=n;i++){
  		for(int j=1;j<=m;j++)ma[1^(i&1)][j].clear();
  		
  		for(int j=1;j<=m;j++){
  		if(i==n && j==m) break;
  		
  		for(auto it=ma[i&1][j].begin();it!=ma[i&1][j].end();it++){
  			if(i!=n){
  				int B=it->first;
  				int val=it->second;
  		//		cout<<i<<" "<<j<<"   "<<bitset<9>(B)<<" "<<val<<endl;
  				B=B<<3;
  				B&=mask;
  				if(ban[i+2][j-1])B|=4;
  				if(ban[i+2][j])B|=2;
  				if(ban[i+2][j+1])B|=1;
  				
  				if(B&(1<<4))val+=ban[i+1][j],B^=(1<<4);
  				vector<pa> ve;
  				if(B&(1<<1))B^=(1<<1),ve.pb(mp(1,ban[i+2][j]));
  				if(B&(1<<3))B^=(1<<3),ve.pb(mp(3,ban[i+1][j+1]));
  				if(B&(1<<5))B^=(1<<5),ve.pb(mp(5,ban[i+1][j-1]));
  				if(B&(1<<7))B^=(1<<7),ve.pb(mp(7,ban[i][j]));
  				if(ve.size()>1){
  					int l=ve.size();
  					int wa=0;
  					for(auto v:ve)wa+=v.second;
  					for(auto v:ve){
  						int B2=(B|(1<<v.first));
  						int val2=val+wa-v.second;
  						if(ma[1^(i&1)][j].find(B2)==ma[1^(i&1)][j].end()) ma[1^(i&1)][j][B2]=val2;
  						else ma[1^(i&1)][j][B2]=min(ma[1^(i&1)][j][B2],val2);
  					}
  				}
  				else{
  					if(ve.size())B|=(1<<ve[0].first);
  					if(ma[1^(i&1)][j].find(B)==ma[1^(i&1)][j].end()) ma[1^(i&1)][j][B]=val;
  					else ma[1^(i&1)][j][B]=min(ma[1^(i&1)][j][B],val);
  				}
  			}
  			if(j!=m){
  				int B=it->first;
  				int val=it->second;
  				B=B<<1;
  				B&=mask;
  				if(B&1)B^=1;
  				if(B&8)B^=8;
  				if(B&64)B^=64;
  				
  				if(ban[i-1][j+2])B|=64;
  				if(ban[i][j+2])B|=8;
  				if(ban[i+1][j+2])B|=1;
  				
  				if(B&(1<<4))val+=ban[i][j+1],B^=(1<<4);
  				vector<pa> ve;
  				if(B&(1<<1))B^=(1<<1),ve.pb(mp(1,ban[i+1][j+1]));
  				if(B&(1<<3))B^=(1<<3),ve.pb(mp(3,ban[i][j+2]));
  				if(B&(1<<5))B^=(1<<5),ve.pb(mp(5,ban[i][j]));
  				if(B&(1<<7))B^=(1<<7),ve.pb(mp(7,ban[i-1][j+1]));
  			//	if(i==1 && j==1)cout<<ve.size()<<endl;
  				if(ve.size()>1){
  					int l=ve.size();
  					int wa=0;
  					for(auto v:ve)wa+=v.second;
  					for(auto v:ve){
  						int B2=(B|(1<<v.first));
  						int val2=val+wa-v.second;
  						if(ma[i&1][j+1].find(B2)==ma[i&1][j+1].end()) ma[i&1][j+1][B2]=val2;
  						else ma[i&1][j+1][B2]=min(ma[i&1][j+1][B2],val2);
  					}
  				}
  				else{
  					if(ve.size())B|=(1<<ve[0].first);
  					if(ma[i&1][j+1].find(B)==ma[i&1][j+1].end()) ma[i&1][j+1][B]=val;
  					else ma[i&1][j+1][B]=min(ma[i&1][j+1][B],val);
  				}
  			}
  		}
  		}
  	}
  	
  	int lasans=inf;
  	for(auto it=ma[n&1][m].begin();it!=ma[n&1][m].end();it++)lasans=min(lasans,it->second);
  	cout<<lasans<<endl;
  	return 0;
                }
accuracy: 1
time_ms: 2010
memory_kb: 7920
final_rank: 11

code_snippet: #include<bits/stdc++.h>
#define all(vec) vec.begin(),vec.end()
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
const ll MOD=1000000007;
const ll INF=1000000010;
const ll LINF=1000000000000000010;
int dx[5]={0,1,0,-1,0};
int dy[5]={1,0,-1,0,0};
char c[1010][1010];
int dp[1010][1010][1<<7];//南、東、北、西、今いる場所、南西、北東
int h,w;
int change(int bit,int dir){
    int res=0;
    if(dir){
        if(bit&(1<<0))res|=(1<<4);//南から今いる場所
        if(bit&(1<<4))res|=(1<<2);//今いる場所から北
        if(bit&(1<<5))res|=(1<<3);//南西から西
        if(bit&(1<<1))res|=(1<<6);//東から北東
    }else{
        if(bit&(1<<0))res|=(1<<5);//南から南西
        if(bit&(1<<1))res|=(1<<4);//東から今いる場所
        if(bit&(1<<4))res|=(1<<3);//今いる場所から西
        if(bit&(1<<6))res|=(1<<2);//北東から北
    }
    return res;
}
int dfs(int y,int x,int bit){
    if(dp[y][x][bit]!=-1)return dp[y][x][bit];
    if(y==h-1&&x==w-1)return 0;
    int res=INF;
    for(int j=0;j<4;j++){
        int s=0;
        int bit2=bit;
        for(int i=0;i<5;i++){
            if(i==j)continue;
            if(bit&(1<<i))continue;
            int ny=y+dy[i];
            int nx=x+dx[i];
            if(ny<0||nx<0||ny>=h||nx>=w)continue;
            if(c[ny][nx]!='.'){
                s+=c[ny][nx]-'0';
                bit2|=(1<<i);
            }
        }
        int a=INF;
        if(y<h-1){
            int nbit=change(bit2,1);
            a=dfs(y+1,x,nbit);
        }
        if(x<w-1){
            int nbit=change(bit2,0);
            a=min(a,dfs(y,x+1,nbit));
        }
        s+=a;
        res=min(res,s);
    }
    return dp[y][x][bit]=res;
}
int main(){
    cin>>h>>w;
    for(int i=0;i<h;i++){
        cin>>c[i];
    }
    memset(dp,-1,sizeof(dp));
    cout<<dfs(0,0,0)<<endl;
}
accuracy: 1
time_ms: 900
memory_kb: 514332
final_rank: 17

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


//到着時の状態
#define Right_North 0
#define North 1
#define Here 2
#define Left 3
#define Left_South 4

//あるマスで調べる状態
#define UE 0
#define HIDARI 1
#define KOKO 2
#define MIGI 3
#define SHITA 4

char input[1000][1001];
int POW[6];
int table[1002][1002];
int min_cost[1002][1002][32];

int H,W;

int main(){

	for(int i = 0; i < 6; i++)POW[i] = pow(2,i);

	scanf("%d %d",&H,&W);

	for(int row = 0; row < H; row++){
		scanf("%s",input[row]);
	}

	//ダミーセルを用意
	for(int col = 0; col <= W+1; col++){
		table[0][col] = 0;
		table[H+1][col] = 0;
	}
	for(int row = 0; row <= H+1; row++){
		table[row][0] = 0;
		table[row][W+1] = 0;
	}

	//マップを転記
	for(int row = 0; row < H; row++){
		for(int col = 0; col < W; col++){
			if(input[row][col] == '.'){
				table[row+1][col+1] = 0;
			}else{
				table[row+1][col+1] = input[row][col]-'0';
			}
		}
	}

	for(int row = 1; row <= H; row++){
		for(int col = 1; col <= W; col++){
			for(int state = 0; state < 32; state++){
				min_cost[row][col][state] = BIG_NUM;
			}
		}
	}

	/*
	 * min_cost[row][col][隣接5箇所の数字を取得したか] = 最小コスト
	 * stateのビット:位置ビットの屋台の菓子を既に食べたか
	 *
	 */
	min_cost[1][1][0] = 0;
	int add_sum,add_loc,removed_add,removed_loc;
	int next_state;
	bool FLG;

	for(int row = 1; row <= H; row++){
		for(int col = 1; col <= W; col++){
			for(int state = 0; state < 32; state++){
				if(min_cost[row][col][state] == BIG_NUM)continue;

				//上下左右+今いる地点で、未加算の数字を調べる
				add_sum = 0,add_loc = 0;

				//上
				if((state & (1 << North)) == 0 && table[row-1][col] != 0){ //上が未加算で、かつ0でない
					add_sum += table[row-1][col];
					add_loc += POW[UE];
				}
				//左
				if((state & (1 << Left)) == 0 && table[row][col-1] != 0){
					add_sum += table[row][col-1];
					add_loc += POW[HIDARI];
				}
				//今いる場所
				if((state & (1 << Here)) == 0 && table[row][col] != 0){
					add_sum += table[row][col];
					add_loc += POW[KOKO];
				}
				//右
				if(table[row][col+1] != 0){
					add_sum += table[row][col+1];
					add_loc += POW[MIGI];
				}
				//下
				if(table[row+1][col] != 0){
					add_sum += table[row+1][col];
					add_loc += POW[SHITA];
				}

				if(add_loc == 0){ //数字を除く必要がない場合

					//右に進む
					next_state = 0;
					if(state & (1 << Right_North)){ //右上→上になる
						next_state += POW[North];
					}
					//今いる場所→左になる
					next_state += POW[Left]; //今いる場所は加算済み、または0、よって右のマスは今のマスを見る必要はない

					//右→「今いる場所になる」
					next_state += POW[Here]; //★add_loc == 0により

					//下は左下になる
					next_state += POW[Left_South]; //★add_loc == 0なので、table[row][col+1]は、新しい左下を無視して良いということ!
					min_cost[row][col+1][next_state] = min(min_cost[row][col+1][next_state],min_cost[row][col][state]);

					//下に進む
					next_state = 0;
					//今いる場所→上になる
					next_state += POW[North];

					if(state & (1 << Left_South)){ //左下→下になる
						next_state += POW[Left];
					}
					//右は右上になる
					next_state += POW[Right_North]; //★add_loc == 0のため
					//下は「今いる場所」になる
					next_state += POW[Here]; //★add_loc == 0のため、無条件で良い

					min_cost[row+1][col][next_state] = min(min_cost[row+1][col][next_state],min_cost[row][col][state]);
					continue;
				}

				//数字を除く必要がある場合

				for(int remove_loc = 0; remove_loc <= 4; remove_loc++){
					if(remove_loc == 2){

						if(add_loc == POW[KOKO]){ //★★今いる場所だけを加算した場合★★

							//右に進む
							next_state = 0;
							if(state & (1 << Right_North)){ //右上→上になる
								next_state += POW[North];
							}
							//今いる場所→左になる
							next_state += POW[Left]; //今いる場所は加算済み、または0、よって右のマスは今のマスを見る必要はない

							//右→「今いる場所になる」
							next_state += POW[Here]; //★add_loc == POW[KOKO]により

							//下は左下になる
							next_state += POW[Left_South]; //★add_loc == POW[KOKO]なので、table[row][col+1]は、新しい左下を無視して良いということ!
							min_cost[row][col+1][next_state] = min(min_cost[row][col+1][next_state],min_cost[row][col][state]+table[row][col]);

							//下に進む
							next_state = 0;
							//今いる場所→上になる
							next_state += POW[North];

							if(state & (1 << Left_South)){ //左下→下になる
								next_state += POW[Left];
							}
							//右は右上になる
							next_state += POW[Right_North]; //★add_loc == POW[KOKO]のため
							//下は「今いる場所」になる
							next_state += POW[Here]; //★add_loc == POW[KOKO]のため、無条件で良い

							min_cost[row+1][col][next_state] = min(min_cost[row+1][col][next_state],min_cost[row][col][state]+table[row][col]);

						}
						continue; //今いる場所は除けない
					}

					FLG = false;

					switch(remove_loc){
					case 0: //上
						if(add_loc & (1 << UE)){
							FLG = true;
							removed_add = add_sum-table[row-1][col];
							removed_loc = UE;
						}
						break;
					case 1: //左
						if(add_loc & (1 << HIDARI)){
							FLG = true;
							removed_add = add_sum-table[row][col-1];
							removed_loc = HIDARI;
						}
						break;
					case 3: //右
						if(add_loc & (1 << MIGI)){
							FLG = true;
							removed_add = add_sum-table[row][col+1];
							removed_loc = MIGI;
						}
						break;
					case 4: //下
						if(add_loc & (1 << SHITA)){
							FLG = true;
							removed_add = add_sum-table[row+1][col];
							removed_loc = SHITA;
						}
						break;
					}
					if(!FLG)continue;

					//右に進む
					next_state = 0;
					if(state & (1 << Right_North)){ //右上→上になる
						next_state += POW[North];
					}
					//今いる場所→左になる
					next_state += POW[Left]; //table[row][col+1]から見れば、仮に左のマスから来たなら、table[row][col]は加算不要なはず(今いるセルは除けないし、0なら無視して良い)

					//右→今いる場所になる
					if(removed_loc != MIGI && (add_loc & (1 << MIGI)) != 0){ //右は除外マスでなく、かつ加算されている
						next_state += POW[Here]; //加算済とする
					}

					//下→左下になる
					if(removed_loc != SHITA && (add_loc & (1 << SHITA)) != 0){ //下は除外マスでなく、かつ加算されている
						next_state += POW[Left_South]; //加算済とする
					}
					min_cost[row][col+1][next_state] = min(min_cost[row][col+1][next_state],min_cost[row][col][state]+removed_add);

					//下に進む
					next_state = 0;
					//今いる場所→上になる
					next_state += POW[North]; //右に進む場合と同様の理由で、無条件で良し

					if(state & (1 << Left_South)){ //左下→下になる
						next_state += POW[Left];
					}
					//右は右上になる
					if(removed_loc != MIGI && (add_loc & (1 << MIGI)) != 0){ //右は除外マスでなく、かつ加算されている
						next_state += POW[Right_North]; //加算済とする
					}
					//下は今いる場所になる
					if(removed_loc != SHITA && (add_loc & (1 << SHITA)) != 0){ //右は除外マスでなく、かつ加算されている
						next_state += POW[Here]; //加算済とする
					}
					min_cost[row+1][col][next_state] = min(min_cost[row+1][col][next_state],min_cost[row][col][state]+removed_add);
				}
			}
		}
	}

	int ans = BIG_NUM;
	for(int state = 0; state < 32; state++){
		ans = min(ans,min_cost[H][W][state]);
	}

	printf("%d\n",ans);

	return 0;
}
accuracy: 1
time_ms: 200
memory_kb: 133648
final_rank: 10