Problem:
お土産購入計画 (Gifts)
問題
オーストラリアに旅行に来た JOI 君は様々な場所で観光を楽しみ，ついに帰国する日がやってきた．今，JOI 君は帰りの飛行機が出発する国際空港のある町にいる．この町は東西南北に区画整理されており，各区画には道，土産店，住宅，国際空港がある．
JOI 君は最も北西の区画から出発して最も南東の区画の国際空港を目指す．
JOI 君は今いる区画から隣り合った区画に移動することができるが，住宅のある区画には入ることはできない．また飛行機の時間に間に合わせるために，今いる区画の東か南の区画にのみ移動する．ただし，時間にはいくらか余裕があるため，K 回まで今いる区画の北か西の区画へ移動することができる．
JOI 君は土産店のある区画に入ると，日本の友人たちのためにお土産を買う．JOI 君は土産店について入念に下調べをしていたので，どの土産店に行ったら何個のお土産を買うことができるかが分かっている．JOI 君が購入できるお土産の個数の最大値を求めるプログラムを作成せよ．
ただし，お土産を買う時間は無視できるとし，同じ土産店に 2 度以上訪れたときは最初に訪れたときだけお土産を買う．
入力
入力は 1 + H 行からなる．
1 行目には，3 つの整数 H, W, K (2 ≦ H ≦ 50, 2 ≦ W ≦ 50, 1 ≦ K ≦ 3) が空白を区切りとして書かれている．
続く H 行にはそれぞれ W 文字からなる文字列が書かれており，区画の情報を表す．北から i 番目，西から j 番目の区画を (i, j) と表す (1 ≦ i ≦ H, 1 ≦ j ≦ W)．
i 行目の j 番目の文字は，区画 (i, j) が道か国際空港である場合は '.' であり，住宅である場合は '#' である．
土産店である場合は '1', '2', ..., '9' のいずれかであり，その土産店で買うことができるお土産の個数を表す．
与えられる入力データにおいては，JOI 君がはじめにいる最も北西の区画が道であることは保証されている．また，JOI 君が国際空港にたどり着けることは保証されている．
出力
JOI 君が購入できるお土産の個数の最大値を表す整数を 1 行で出力せよ．
入出力例
入力例 1
5 4 2
...#
.#.#
.#73
8##.
....
出力例 1
11
入出力例 1 において，JOI 君は 3 回南へ進み区画 (4, 1) の土産店で買い物をした後，さらに南へ 1 回，東へ 3 回進み，そこから北へ 2 回進むことで区画 (3, 4) の土産店で買い物をする．最後に南へ 2 回進んで国際空港へたどり着くと，合計で 11 個のお土産を買うことができる．
入力例 2
4 4 3
.8#9
9.#.
.#9.
....
出力例 2
27
問題文と自動審判に使われるデータは、
情報オリンピック日本委員会
が作成し公開している問題文と採点用テストデータです。

Submitted solutions:

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

#include<atcoder/modint>
using namespace atcoder;
using mint=modint998244353;

using ll =long long;


void solve(){
    
    

}

map<set<array<ll,2>>,ll> DP[51][51][5];
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int N,M,K;
    cin>>N>>M>>K;

    vector<string> S(N);
    for(int i=0;i<N;i++)cin>>S[i];

    DP[0][0][K][{}]=0;
    vector<int> nd={0,1,0,-1,0};
    for(ll k=K;k>=0;k--){
        for(int i=0;i<N;i++){
            for(int j=0;j<M;j++){
                for(auto [ST,n]:DP[i][j][k]){
                    for(int d=0;d<4;d++){
                        if(d>1&&k==0)break;
                        ll ni=i+nd[d];
                        ll nj=j+nd[d+1];
                        if(ni<0||nj<0||ni>=N||nj>=M)continue;
                        if(S[ni][nj]=='#')continue;
                        ll nk=k;
                        ll nc=n;
                        if(d>1)nk--;
                        
                        set<array<ll,2>> NS;
                        for(auto [y,x]:ST){
                            if(abs(y-ni)+abs(x-nj)<=k+1){
                                NS.insert({y,x});
                            }
                        }
                        if(S[ni][nj]!='.'){
                            if(!ST.count({ni,nj})){
                                nc+=S[ni][nj]-'0';
                                NS.insert({ni,nj});
                            }
                        }
                        DP[ni][nj][nk][NS]=max(DP[ni][nj][nk][NS],nc);
                    }
                    
                }
                if(i!=N-1||j!=M-1)DP[i][j][k].clear();
            }
        }
    }

    ll an=0;
    for(int k=0;k<=K;k++){
        for(auto [S,n]:DP[N-1][M-1][k])an=max(an,n);
    }
    cout<<an<<"\n";
    
    
}
accuracy: 1
time_ms: 1230
memory_kb: 114432
final_rank: 5

code_snippet: #include <iostream>
#include <vector>
#include <map>
#include <string>
#include <queue>
#include <set>
#include <string.h>
#include <algorithm>
using namespace std;
struct E{
	vector<int> vs;
	int v;
	int k;
	int xr;
	int yd;
	bool operator<(const E& e)const{
		return v<e.v;
	}
};
struct E2{
	int x,y;
	bool operator<(const E2 e2)const{
		if(x!=e2.x)return x<e2.x;
		return y<e2.y;
	}
};
int z=0;

map<vector<int>,int> dp[4];
map<vector<int>,int> dp2[4][51][51];
set<E2> nextxy;
//map<set<int>,int> dp[4][2501];
string ms[51];
priority_queue<E> qs;
int search(vector<int> vs,int p){
	for(int i=0;i<vs.size();i++){
		if(vs[i]==p)return 0;
	}
	return 1;
}
bool rowok(int p1,int p2,int w){
	return p1/w==p2/w;
}
void dell(vector<int> & vs,int p1,int w,int k1){
	int x1=p1%w;
	int y1=p1/w;
	
	for(vector<int>::iterator it=vs.begin();it!=vs.end();){
		int x2,y2,d=0;
		x2=(*it)%w;
		y2=(*it)/w;
		
		if(x1-x2>0){
			d+=x1-x2;
		}
		if(y1-y2>0){
			d+=y1-y2;
		}
		if(d>k1){
			it=vs.erase(it);
		}else{
			it++;
		}
		if(it==vs.end())break;
	}
	
}

void add(E e,int addk,int p1,int h,int w,int k){
	int m1=h*w;
	if(p1<0 || m1<=p1)return ;
	int x=p1%w;
	int y=p1/w;
	if(ms[y][x]=='#')return ;
	
	e.k+=addk;
	if(e.k>k)return ;
	//if(100<z && z<200)cout<<e.vs.size()<<" ";
	dell(e.vs,p1,w,k-e.k);
	
	int m2=search(e.vs,p1);
	if(ms[y][x]!='.'){
		e.v+=(ms[y][x]-'0')*m2;
	}
	e.vs.push_back(p1);
	
	//if(100<z && z<200)cout<<e.vs.size()<<" "<<e.v<<endl;
	//set<int> s1;
	//s1.insert(e.vs.begin(),e.vs.end());
	int t=-1;
	if(dp[e.k].find(e.vs)!=dp[e.k].end())t=dp[e.k][e.vs];
	//if(dp[e.k][p1].find(s1)!=dp[e.k][p1].end())t=dp[e.k][p1][s1];
	//cout<<x<<" "<<y<<" "<<p1<<" "<<t<<" "<<e.v<<endl;
	if(e.v>t){
		dp[e.k][e.vs]=e.v;
		if(e.xr<x || e.yd<y){
			dp2[e.k][y][x][e.vs]=max(dp2[e.k][y][x][e.vs],e.v);
			E2 e2;
			e2.x=x;
			e2.y=y;
			nextxy.insert(e2);
		}else{
			//dp[e.k][p1][s1]=e.v;
			qs.push(e);
		}
	}
}

int main() {
	int h,w,k;
	cin>>h>>w>>k;
	for(int i=0;i<h;i++){
		cin>>ms[i];
	}
	vector<int> v1;
	v1.push_back(0);
	dp2[0][0][0][v1]=0;
	E2 e2;
	e2.x=0;
	e2.y=0;
	nextxy.insert(e2);
	
	int ans=0;
	while(nextxy.size()>0){
		for(set<E2>::iterator its=nextxy.begin();its!=nextxy.end();its++){
			int xr=(*its).x;
			int yd=(*its).y;
			for(int nowk=0;nowk<=k;nowk++){
				for(map<vector<int>,int>::iterator it=dp2[nowk][yd][xr].begin();it!=dp2[nowk][yd][xr].end();it++){
					E e;
					e.vs=(*it).first;
					e.v=(*it).second;
					e.k=nowk;
					e.xr=xr;
					e.yd=yd;
					qs.push(e);
				}
				dp2[nowk][yd][xr].clear();
			}
		}
		nextxy.clear();
		while(qs.size()>0){
			E e=qs.top();
			qs.pop();
			int p1=e.vs[e.vs.size()-1];
			int x=p1%w;
			int y=p1/w;
			//cout<<x<<" "<<y<<endl;
			if(x==w-1 && y==h-1 && ans<e.v){
				ans=e.v;
			}
			//274
			add(e,0,p1+w,h,w,k);
			add(e,1,p1-w,h,w,k);
			if(rowok(p1,p1+1,w)){
				add(e,0,p1+1,h,w,k);//堀江
			}
			if(rowok(p1,p1-1,w)){
				add(e,1,p1-1,h,w,k);
			}
		}
	}
	cout<<ans<<endl;
	return 0;
}
accuracy: 1
time_ms: 3640
memory_kb: 161852
final_rank: 12

code_snippet: #include <iostream>
#include <vector>
#include <map>
#include <string>
#include <queue>
#include <set>
#include <string.h>
using namespace std;
struct E{
	vector<int> vs;
	int v;
	int k;
	bool operator<(const E& e)const{
		return v<e.v;
	}
};
int dp[4][2502];
string ms[51];
priority_queue<E> qs;
int search(vector<int> vs,int p){
	for(int i=0;i<vs.size();i++){
		if(vs[i]==p)return 0;
	}
	return 1;
}
bool rowok(int p1,int p2,int w){
	return p1/w==p2/w;
}
void add(E e,int addk,int p1,int h,int w,int k){
	int m1=h*w;
	if(p1<0 || m1<=p1)return ;
	int x=p1%w;
	int y=p1/w;
	if(ms[y][x]=='#')return ;
	if(ms[y][x]!='.'){
		e.v+=(ms[y][x]-'0')*search(e.vs,p1);
	}
	
	e.vs.push_back(p1);
	if(e.vs.size()>7)e.vs.erase(e.vs.begin());
	e.k+=addk;
	if(e.k>k)return ;
	
	int t=dp[e.k][p1];

	//cout<<x<<" "<<y<<" "<<p1<<" "<<t<<" "<<e.v<<endl;
	if(e.v>t){
		dp[e.k][p1]=e.v;
		qs.push(e);
	}
}

int main() {
	int h,w,k;
	cin>>h>>w>>k;
	for(int i=0;i<h;i++){
		cin>>ms[i];
	}
	E e;
	e.vs.push_back(0);
	e.v=0;
	e.k=0;
	qs.push(e);
	memset(dp,-1,sizeof(dp));
	int ans=0;
	while(qs.size()>0){
		E e=qs.top();
		qs.pop();
		int p1=e.vs[e.vs.size()-1];
		int x=p1%w;
		int y=p1/w;
		//cout<<x<<" "<<y<<endl;
		if(x==w-1 && y==h-1 && ans<e.v){
			ans=e.v;
			continue;
		}
		//704
		add(e,0,p1+w,h,w,k);
		add(e,1,p1-w,h,w,k);
		if(rowok(p1,p1+1,w)){
			add(e,0,p1+1,h,w,k);
		}
		if(rowok(p1,p1-1,w)){
			add(e,1,p1-1,h,w,k);
		}
	}
	cout<<ans<<endl;
	return 0;
}
accuracy: 0.8
time_ms: 130
memory_kb: 3288
final_rank: 16

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

#define rep(i, x) for (int i = 0; i < x; i++)
#define rep2(i, x) for (int i = 1; i <= x; i++)
#define rep3(i, x, y) for (int i = x; i < y; i++)
#define REP(i, x) for (int i = x - 1; i >= 0; i--)
#define REP2(i, x) for (int i = x; i >= 1; i--)
#define mpa make_pair
#define mpt make_tuple
#define pb push_back
#define all(a) (a).begin(), (a).end()
#define rall(a) (a).rbegin(), (a).rend()
#define puts(x) cout << (x) << "\n"
using ll = long long;
using ld = long double;
using namespace std;
// using namespace atcoder;

const ll INF = 1000000000000000000;
const int intINF = 1000000000;
const ll mod = 1000000007;
const ll MOD = 998244353;
const ld pi = acos(-1);
// const ld EPS = 1e-9;
typedef string::const_iterator State;
class ParseError
{
};

template <typename T>
bool chmax(T &a, const T &b)
{
    if (a < b)
    {
        a = b; // aをbで更新
        return true;
    }
    return false;
}
template <typename T>
bool chmin(T &a, const T &b)
{
    if (a > b)
    {
        a = b; // aをbで更新
        return true;
    }
    return false;
}

struct Point
{
    int x, y;
    bool operator!=(const Point &p) const noexcept { return (x != p.x || y != p.y); }
};
// 左上右下
int dx[4] = {0, -1, 0, 1};
int dy[4] = {-1, 0, 1, 0};

char grid[55][55];
int dp[4][51][51][4][4][4][4][4];
// dp[k][x][y][d1][d2][d3][d4][d5]
//  今(x,y)にいてk回上左に行ってて前の行動がpre1~5の時の、お土産の個数の最大値

int main()
{
    ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    // cout << fixed << setprecision(15);
    // priority_queue<ll, vector<ll>, greater<ll>> que;
    // priority_queue<P, vector<P>, greater<P>> que;
    // priority_queue<status, vector<status>, greater<status>> que;

    ////////////////////
    //
    //   初期化
    //
    rep(k, 4)
    {
        rep(x, 51)
        {
            rep(y, 51)
            {
                rep(d1, 4)
                {
                    rep(d2, 4)
                    {
                        rep(d3, 4)
                        {
                            rep(d4, 4)
                            {
                                rep(d5, 4)
                                {
                                    dp[k][x][y][d1][d2][d3][d4][d5] = -1;
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    ////////////////////
    //
    //   input
    //

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

    rep2(x, h)
    {
        rep2(y, w)
        {
            cin >> grid[x][y];
        }
    }

    ////////////////////
    //
    //   DP
    //

    int ans = 0;
    dp[0][1][1][0][0][0][0][0] = 0;
    rep2(x, h)
    {
        rep2(y, w)
        {
            if (grid[x][y] == '#')
            {
                continue;
            }
            int cnt = 0;
            if (grid[x][y] != '.')
            {
                cnt = grid[x][y] - '0';
            }
            rep(d1, 4)
            {
                rep(d2, 4)
                {
                    rep(d3, 4)
                    {
                        rep(d4, 4)
                        {
                            rep3(l, 2, 4)
                            {
                                int prex = 0, prey = 0;
                                prex = x - dx[l], prey = y - dy[l];
                                int ma = -1;
                                rep(d0, 4)
                                {
                                    chmax(ma, dp[0][prex][prey][d0][d1][d2][d3][d4]);
                                }
                                if (ma == -1)
                                {
                                    continue;
                                }
                                dp[0][x][y][d1][d2][d3][d4][l] = ma + cnt;
                                if (x == h && y == w)
                                {
                                    chmax(ans, dp[0][x][y][d1][d2][d3][d4][l]);
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    rep2(k, K)
    {
        ////////////////////
        //
        //   k-1 -> k
        //

        REP2(x, h)
        {
            REP2(y, w)
            {
                if (grid[x][y] == '#')
                {
                    continue;
                }

                int cnt = 0;
                if (grid[x][y] != '.')
                {
                    cnt = grid[x][y] - '0';
                }
                rep(d1, 4)
                {
                    rep(d2, 4)
                    {
                        rep(d3, 4)
                        {
                            rep(d4, 4)
                            {
                                rep(l, 2)
                                {
                                    int prex = x - dx[l], prey = y - dy[l];
                                    Point p1 = {prex, prey};
                                    Point p2 = {p1.x - dx[d4], p1.y - dy[d4]};
                                    Point p3 = {p2.x - dx[d3], p2.y - dy[d3]};
                                    Point p4 = {p3.x - dx[d2], p3.y - dy[d2]};
                                    Point p5 = {p4.x - dx[d1], p4.y - dy[d1]};

                                    int ma = -1;
                                    rep(d0, 4)
                                    {
                                        chmax(ma, dp[k - 1][prex][prey][d0][d1][d2][d3][d4]);
                                    }
                                    if (ma == -1)
                                    {
                                        continue;
                                    }

                                    Point p = {x, y};
                                    int cnt2 = 0;
                                    if (p != p1 && p != p2 && p != p2 && p != p3 && p != p4 && p != p5)
                                    {
                                        cnt2 = cnt;
                                    }

                                    dp[k][x][y][d1][d2][d3][d4][l] = ma + cnt2;
                                    if (x == h && y == w)
                                    {
                                        chmax(ans, dp[k][x][y][d1][d2][d3][d4][l]);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        ////////////////////
        //
        //   k -> k
        //

        rep2(x, h)
        {
            rep2(y, w)
            {
                if (grid[x][y] == '#')
                {
                    continue;
                }

                int cnt = 0;
                if (grid[x][y] != '.')
                {
                    cnt = grid[x][y] - '0';
                }
                rep(d1, 4)
                {
                    rep(d2, 4)
                    {
                        rep(d3, 4)
                        {
                            rep(d4, 4)
                            {
                                rep3(l, 2, 4)
                                {
                                    int prex = 0, prey = 0;
                                    prex = x - dx[l], prey = y - dy[l];
                                    Point p1 = {prex, prey};
                                    Point p2 = {p1.x - dx[d4], p1.y - dy[d4]};
                                    Point p3 = {p2.x - dx[d3], p2.y - dy[d3]};
                                    Point p4 = {p3.x - dx[d2], p3.y - dy[d2]};
                                    Point p5 = {p4.x - dx[d1], p4.y - dy[d1]};

                                    int ma = -1;
                                    rep(d0, 4)
                                    {
                                        chmax(ma, dp[k][prex][prey][d0][d1][d2][d3][d4]);
                                    }
                                    if (ma == -1)
                                    {
                                        continue;
                                    }

                                    
                                    Point p = {x, y};
                                    int cnt2 = 0;
                                    if (p != p1 && p != p2 && p != p2 && p != p3 && p != p4 && p != p5)
                                    {
                                        cnt2 = cnt;
                                    }

                                    dp[k][x][y][d1][d2][d3][d4][l] = ma + cnt2;
                                    if (x == h && y == w)
                                    {
                                        chmax(ans, dp[k][x][y][d1][d2][d3][d4][l]);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    cout << ans << endl;
    return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 45060
final_rank: 1

code_snippet: #if 1
#define _CRT_SECURE_NO_WARNINGS

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <queue>
#include <stack>
#include <array>
#include <deque>
#include <algorithm>
#include <utility>
#include <cstdint>
#include <functional>
#include <iomanip>
#include <numeric>
#include <assert.h>
#include <bitset>
#include <list>
#include <cmath>
#include <array>
//#include <atcoder/all>

auto& in = std::cin;
auto& out = std::cout;
#define all_range(C) std::begin(C), std::end(C)
const int MOD = 10007;

int H, W, K;
char map[52][52];

std::unordered_map<uint32_t, int16_t> dp[52][52][4];

uint32_t myencode(int h, int w, const std::array<std::pair<int8_t, int8_t>, 6>& visited) {

	std::pair<int8_t, int8_t> now = { h,w };
	uint32_t mask = 0;
	for (int i = visited.size()-1; i >= 0; --i)
	{
		if (visited[i].first == now.first) {
			if (visited[i].second == now.second - 1) {
				mask |= 0;
			}
			else {
				assert((visited[i].second == now.second + 1) || (visited[i] == std::pair<int8_t, int8_t>{ 0, 0 }));
				mask |= 1;
			}
		}
		else {
			if (visited[i].first == now.first - 1) {
				mask |= 2;
			}
			else {
				assert((visited[i].first == now.first + 1) || (visited[i] == std::pair<int8_t, int8_t>{ 0,0 }));
				mask |= 3;
			}
		}

		mask <<= 2;
		now = visited[i];
	}
	return mask;
}

int16_t func(int h, int w, int k, std::array<std::pair<int8_t, int8_t>, 6> visited) {

	if (map[h][w] == '#') {
		return -5509;
	}
	if (k == 0 && h == H && w == W) {
		return 0;
	}
	assert(0 <= h);
	assert(0 <= w);
	auto& memo_map = dp[h][w][k];
	if (k == 0) {
		for (size_t i = 0; i < visited.size(); i++) {
			if (!(visited[i].first < h || visited[i].second < w)) {
				break;
			}
			visited[i] = {};
		}
	}
	if (k == 3) {
		visited[0] = {};
		visited[1] = {};
		visited[2] = {};
	}
	auto enc_v = myencode(h,w,visited);
	if (memo_map.count(enc_v) != 0) {
		return memo_map[enc_v];
	}
	auto& memo = memo_map[enc_v];
	memo = -5509;
	if (h == H && w == W) {
		memo = 0;
	}

	std::array<std::pair<int8_t, int8_t>, 6> next_visited = { visited[1], visited[2], visited[3], visited[4], visited[5], {(int8_t)h,(int8_t)w} };
	if (map[h][w + 1] != '#') {
		bool getable = (map[h][w + 1] != '.');
		getable &= std::count(all_range(visited), std::pair<int8_t, int8_t>{h, w + 1}) == 0;
		memo = std::max<int16_t>(memo, (getable ? (map[h][w + 1] - '0') : 0) + func(h, w + 1, k, next_visited));
	}
	if (map[h + 1][w] != '#') {
		bool getable = (map[h + 1][w] != '.');
		getable &= std::count(all_range(visited), std::pair<int8_t, int8_t>{h + 1, w}) == 0;
		memo = std::max<int16_t>(memo, (getable ? (map[h + 1][w] - '0') : 0) + func(h + 1, w, k, next_visited));
	}

	if (k > 0) {
		if (map[h][w - 1] != '#') {
			bool getable = (map[h][w - 1] != '.');
			getable &= std::count(all_range(visited), std::pair<int8_t, int8_t>{h, w - 1}) == 0;
			memo = std::max<int16_t>(memo, (getable ? (map[h][w - 1] - '0') : 0) + func(h, w - 1, k - 1, next_visited));
		}
		if (map[h - 1][w] != '#') {
			bool getable = (map[h - 1][w] != '.');
			getable &= std::count(all_range(visited), std::pair<int8_t, int8_t>{h - 1, w}) == 0;
			memo = std::max<int16_t>(memo, (getable ? (map[h - 1][w] - '0') : 0) + func(h - 1, w, k - 1, next_visited));
		}
	}

	if (memo < 0) {
		memo = -5509;
	}
	return memo;
}


template<typename T, typename U>
std::enable_if_t<std::rank<T>::value == 0> fill_all(T& arr, const U& v) {
	arr = v;
}
template<typename ARR, typename U>
std::enable_if_t<std::rank<ARR>::value != 0> fill_all(ARR& arr, const U& v) {
	for (auto& i : arr) {
		fill_all(i, v);
	}
}

int main()
{
	using std::endl;

	//in >> H >> W >> K;
	scanf("%d", &H);
	scanf("%d", &W);
	scanf("%d", &K);
	fill_all(map, '#');
	for (size_t i = 1; i <= H; i++)
	{
		scanf("%s", &map[i][1]);
		assert(map[i][W + 1] == '\0');
		map[i][W + 1] = '#';
	}
	out << func(1, 1, K, {}) << endl;


	return 0;
}
#endif
accuracy: 1
time_ms: 2180
memory_kb: 234948
final_rank: 13

code_snippet: #if 1
#define _CRT_SECURE_NO_WARNINGS

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <queue>
#include <stack>
#include <array>
#include <deque>
#include <algorithm>
#include <utility>
#include <cstdint>
#include <functional>
#include <iomanip>
#include <numeric>
#include <assert.h>
#include <bitset>
#include <list>
#include <cmath>
#include <array>
//#include <atcoder/all>

auto& in = std::cin;
auto& out = std::cout;
#define all_range(C) std::begin(C), std::end(C)
const int MOD = 10007;

int H, W, K;
char map[52][52];

std::map<uint32_t, int16_t> dp[52][52][4];

uint32_t myencode(int h, int w, const std::array<std::pair<int8_t, int8_t>, 6>& visited) {

	std::pair<int8_t, int8_t> now = { h,w };
	uint32_t mask = 0;
	for (size_t i = 0; i < visited.size(); i++)
	{
		if (visited[i].first == now.first) {
			if (visited[i].second == now.second + 1) {
				mask |= 0;
			}
			else {
				mask |= 1;
			}
		}
		else {
			if (visited[i].first == now.first - 1) {
				mask |= 2;
			}
			else {
				mask |= 3;
			}
		}

		mask <<= 2;
		now = visited[i];
	}
	return mask;
}

int16_t func(int h, int w, int k, std::array<std::pair<int8_t, int8_t>, 6> visited) {

	if (map[h][w] == '#') {
		return -5509;
	}
	if (k == 0 && h == H && w == W) {
		return 0;
	}
	auto& memo_map = dp[h][w][k];
	auto enc_v = myencode(h,w,visited);
	if (memo_map.count(enc_v) != 0) {
		return memo_map[enc_v];
	}
	auto& memo = memo_map[enc_v];
	memo = -5509;
	if (h == H && w == W) {
		memo = 0;
	}

	std::array<std::pair<int8_t, int8_t>, 6> next_visited = { visited[1], visited[2], visited[3], visited[4], visited[5], {(int8_t)h,(int8_t)w} };
	if (map[h][w + 1] != '#') {
		bool getable = (map[h][w + 1] != '.');
		getable &= std::count(all_range(visited), std::pair<int8_t, int8_t>{h, w + 1}) == 0;
		memo = std::max<int16_t>(memo, (getable ? (map[h][w + 1] - '0') : 0) + func(h, w + 1, k, next_visited));
	}
	if (map[h + 1][w] != '#') {
		bool getable = (map[h + 1][w] != '.');
		getable &= std::count(all_range(visited), std::pair<int8_t, int8_t>{h + 1, w}) == 0;
		memo = std::max<int16_t>(memo, (getable ? (map[h + 1][w] - '0') : 0) + func(h + 1, w, k, next_visited));
	}

	if (k > 0) {
		if (map[h][w - 1] != '#') {
			bool getable = (map[h][w - 1] != '.');
			getable &= std::count(all_range(visited), std::pair<int8_t, int8_t>{h, w - 1}) == 0;
			memo = std::max<int16_t>(memo, (getable ? (map[h][w - 1] - '0') : 0) + func(h, w - 1, k - 1, next_visited));
		}
		if (map[h - 1][w] != '#') {
			bool getable = (map[h - 1][w] != '.');
			getable &= std::count(all_range(visited), std::pair<int8_t, int8_t>{h - 1, w}) == 0;
			memo = std::max<int16_t>(memo, (getable ? (map[h - 1][w] - '0') : 0) + func(h - 1, w, k - 1, next_visited));
		}
	}

	if (memo < 0) {
		memo = -5509;
	}
	return memo;
}


template<typename T, typename U>
std::enable_if_t<std::rank<T>::value == 0> fill_all(T& arr, const U& v) {
	arr = v;
}
template<typename ARR, typename U>
std::enable_if_t<std::rank<ARR>::value != 0> fill_all(ARR& arr, const U& v) {
	for (auto& i : arr) {
		fill_all(i, v);
	}
}

int main()
{
	using std::endl;

	//in >> H >> W >> K;
	scanf("%d", &H);
	scanf("%d", &W);
	scanf("%d", &K);
	fill_all(map, '#');
	for (size_t i = 1; i <= H; i++)
	{
		scanf("%s", &map[i][1]);
		map[i][W + 1] = '#';
	}
	out << func(1, 1, K, {}) << endl;


	return 0;
}
#endif
accuracy: 0.2
time_ms: 470
memory_kb: 55376
final_rank: 19

code_snippet: #include <bits/stdc++.h>
#pragma GCC optimize("Ofast")
#define _GLIBCXX_DEBUG
using namespace std;
using std::cout;
using std::cin;
using std::endl;
using ll=long long;
using ld=long double;
ll ILL=2167167167167167167;
const int INF=2100000000;
const int mod=10007;
#define rep(i,a) for (ll i=0;i<a;i++)
#define all(p) p.begin(),p.end()
template<class T> using _pq = priority_queue<T, vector<T>, greater<T>>;
template<class T> ll LB(vector<T> &v,T a){return lower_bound(v.begin(),v.end(),a)-v.begin();}
template<class T> ll UB(vector<T> &v,T a){return upper_bound(v.begin(),v.end(),a)-v.begin();}
template<class T> bool chmin(T &a,const T &b){if(a>b){a=b;return 1;}else return 0;}
template<class T> bool chmax(T &a,const T &b){if(a<b){a=b;return 1;}else return 0;}
template<class T> void So(vector<T> &v) {sort(v.begin(),v.end());}
template<class T> void Sore(vector<T> &v) {sort(v.begin(),v.end(),[](T x,T y){return x>y;});}
void yneos(bool a){if(a) cout<<"Yes\n"; else cout<<"No\n";}
template<class T> void vec_out(vector<T> &p){for(int i=0;i<(int)(p.size());i++){if(i) cout<<" ";cout<<p[i];}cout<<"\n";}

#define vec5 vector<vector<vector<vector<vector<int>>>>>
#define vec4 vector<vector<vector<vector<int>>>>
#define vec3 vector<vector<vector<int>>>
#define vec2 vector<vector<int>>
#define vec1 vector<int>

void solve();
// oddloop
int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	
	int t=1;
	//cin>>t;
	rep(i,t) solve();
}

void solve(){
	int H,W,K;
	cin>>H>>W>>K;
	vector<vector<int>> p(H,vector<int>(W));
	rep(i,H) rep(j,W){
		char c;
		cin>>c;
		if(c=='#') p[i][j]=-1;
		else if(c!='.') p[i][j]=(int)(c-'0');
	}
	vector<int> A={0,1,3,2,4,5},B={2,4,7,5,8,9},C={1,3,6,4,7,8};
	//int dp[H][W][K+1][1024][4];
	vector<int> dp(H*W*1024*4,-1);
	auto n_dp=dp;
	/*string po;
	cin>>po;*/
	auto f=[&](int a,int b,int c,int d){
		return a*W*1024*4+b*1024*4+c*4+d;
	};
	dp[4]=0;
	n_dp[4]=0;
	rep(k,K+1){
		rep(i,H) rep(j,W) rep(s,1024) rep(l,4){
		if(dp[f(i,j,s,l)]==-1) continue;
		int tmp,val,X=(l+k*(k+1)/2),Z=dp[f(i,j,s,l)];
		val=Z;
		if(i!=H-1&&p[i+1][j]!=-1){
			tmp=0;
			rep(roop,6) if(s&(1<<A[roop])) tmp+=(1<<B[roop]);
			if((tmp&(1<<X))==0) tmp+=(1<<X),val+=p[i+1][j];
			chmax(dp[f(i+1,j,tmp,l)],val);
		}
		val=Z;
		if(j!=W-1&&p[i][j+1]!=-1){
			tmp=0;
			rep(roop,6) if(s&(1<<A[roop])) tmp+=(1<<C[roop]);
			if((tmp&(1<<X))==0) tmp+=(1<<X),val+=p[i][j+1];
			chmax(dp[f(i,j+1,tmp,l)],val);
		}
		val=Z;
		if(k!=K&&i!=0&&p[i-1][j]!=-1){
			tmp=s;
			int n_X=k+2+X;
			if((tmp&(1<<n_X))==0) tmp+=(1<<n_X),val+=p[i-1][j];
			chmax(n_dp[f(i-1,j,tmp,l+1)],val);
		}
		val=Z;
		if(k!=K&&j!=0&&p[i][j-1]!=-1){
			tmp=s;
			int n_X=k+1+X;
			if((tmp&(1<<n_X))==0) tmp+=(1<<n_X),val+=p[i][j-1];
			chmax(n_dp[f(i,j-1,tmp,l)],val);
		}
		}
		swap(n_dp,dp);
	}
	int ans=0;
	rep(k,K+1) rep(s,1024) rep(l,4) chmax(ans,n_dp[f(H-1,W-1,s,l)]);
	cout<<ans<<"\n";
}
accuracy: 1
time_ms: 80
memory_kb: 83160
final_rank: 4

code_snippet: #if 1
#define _CRT_SECURE_NO_WARNINGS

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <queue>
#include <stack>
#include <array>
#include <deque>
#include <algorithm>
#include <utility>
#include <cstdint>
#include <functional>
#include <iomanip>
#include <numeric>
#include <assert.h>
#include <bitset>
#include <list>
#include <cmath>
#include <array>
//#include <atcoder/all>

auto& in = std::cin;
auto& out = std::cout;
#define all_range(C) std::begin(C), std::end(C)
const int MOD = 10007;

int H, W, K;
char map[52][52];

std::map<uint32_t, int16_t> dp[52][52][4];

uint32_t myencode(int h, int w, const std::array<std::pair<int8_t, int8_t>, 6>& visited) {

	std::pair<int8_t, int8_t> now = { h,w };
	uint32_t mask = 0;
	for (size_t i = 0; i < visited.size(); i++)
	{
		if (visited[i].first == now.first) {
			if (visited[i].second == now.second + 1) {
				mask |= 0;
			}
			else {
				mask |= 1;
			}
		}
		else {
			if (visited[i].first == now.first + 1) {
				mask |= 2;
			}
			else {
				mask |= 3;
			}
		}

		mask <<= 2;
		now = visited[i];
	}
	return mask;
}

int16_t func(int h, int w, int k, std::array<std::pair<int8_t, int8_t>, 6> visited) {

	if (map[h][w] == '#') {
		return -5509;
	}
	if (k == 0 && h == H && w == W) {
		return 0;
	}
	auto& memo_map = dp[h][w][k];
	auto enc_v = myencode(h,w,visited);
	if (memo_map.count(enc_v) != 0) {
		return memo_map[enc_v];
	}
	auto& memo = memo_map[enc_v];
	memo = -5509;
	if (h == H && w == W) {
		memo = 0;
	}

	std::array<std::pair<int8_t, int8_t>, 6> next_visited = { visited[1], visited[2], visited[3], visited[4], visited[5], {(int8_t)h,(int8_t)w} };
	if (map[h][w + 1] != '#') {
		bool getable = (map[h][w + 1] != '.');
		getable &= std::count(all_range(visited), std::pair<int8_t, int8_t>{h, w + 1}) == 0;
		memo = std::max<int16_t>(memo, (getable ? (map[h][w + 1] - '0') : 0) + func(h, w + 1, k, next_visited));
	}
	if (map[h + 1][w] != '#') {
		bool getable = (map[h + 1][w] != '.');
		getable &= std::count(all_range(visited), std::pair<int8_t, int8_t>{h + 1, w}) == 0;
		memo = std::max<int16_t>(memo, (getable ? (map[h + 1][w] - '0') : 0) + func(h + 1, w, k, next_visited));
	}

	if (k > 0) {
		if (map[h][w - 1] != '#') {
			bool getable = (map[h][w - 1] != '.');
			getable &= std::count(all_range(visited), std::pair<int8_t, int8_t>{h, w - 1}) == 0;
			memo = std::max<int16_t>(memo, (getable ? (map[h][w - 1] - '0') : 0) + func(h, w - 1, k - 1, next_visited));
		}
		if (map[h - 1][w] != '#') {
			bool getable = (map[h - 1][w] != '.');
			getable &= std::count(all_range(visited), std::pair<int8_t, int8_t>{h - 1, w}) == 0;
			memo = std::max<int16_t>(memo, (getable ? (map[h - 1][w] - '0') : 0) + func(h - 1, w, k - 1, next_visited));
		}
	}

	if (memo < 0) {
		memo = -5509;
	}
	return memo;
}


template<typename T, typename U>
std::enable_if_t<std::rank<T>::value == 0> fill_all(T& arr, const U& v) {
	arr = v;
}
template<typename ARR, typename U>
std::enable_if_t<std::rank<ARR>::value != 0> fill_all(ARR& arr, const U& v) {
	for (auto& i : arr) {
		fill_all(i, v);
	}
}

int main()
{
	using std::endl;

	//in >> H >> W >> K;
	scanf("%d", &H);
	scanf("%d", &W);
	scanf("%d", &K);
	fill_all(map, '#');
	for (size_t i = 1; i <= H; i++)
	{
		scanf("%s", &map[i][1]);
		map[i][W + 1] = '#';
	}


	out << func(1, 1, K, {}) << endl;


	return 0;
}
#endif
accuracy: 0.2
time_ms: 210
memory_kb: 31352
final_rank: 17

code_snippet: #if 1
#define _CRT_SECURE_NO_WARNINGS

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <queue>
#include <stack>
#include <array>
#include <deque>
#include <algorithm>
#include <utility>
#include <cstdint>
#include <functional>
#include <iomanip>
#include <numeric>
#include <assert.h>
#include <bitset>
#include <list>
#include <cmath>
#include <array>
//#include <atcoder/all>

auto& in = std::cin;
auto& out = std::cout;
#define all_range(C) std::begin(C), std::end(C)
const int MOD = 10007;

int H, W, K;
char map[52][52];

std::map<uint32_t, int16_t> dp[52][52][4];

uint32_t myencode(int h, int w, const std::array<std::pair<int8_t, int8_t>, 6>& visited) {

	std::pair<int8_t, int8_t> now = { h,w };
	uint32_t mask = 0;
	for (size_t i = 0; i < visited.size(); i++)
	{
		if (visited[i].first == now.first) {
			if (visited[i].second == now.second + 1) {
				mask |= 0;
			}
			else {
				mask |= 1;
			}
		}
		else {
			if (visited[i].first == now.first + 1) {
				mask |= 2;
			}
			else {
				mask |= 3;
			}
		}

		mask <<= 2;
		now = visited[i];
	}
	return mask;
}

int16_t func(int h, int w, int k, std::array<std::pair<int8_t, int8_t>, 6> visited) {

	if (map[h][w] == '#') {
		return -5509;
	}
	if (k == 0 && h == H && w == W) {
		return 0;
	}
	auto& memo_map = dp[h][w][k];
	auto enc_v = myencode(h,w,visited);
	if (memo_map.count(enc_v) != 0) {
		return memo_map[enc_v];
	}
	auto& memo = memo_map[enc_v];
	memo = -5509;
	if (h == H && w == W) {
		memo = 0;
	}

	std::array<std::pair<int8_t, int8_t>, 6> next_visited = { visited[1], visited[2], visited[3], visited[4], visited[5], {(int8_t)h,(int8_t)w} };
	if (map[h][w + 1] != '#') {
		bool getable = (map[h][w + 1] != '.');
		getable &= std::count(all_range(visited), std::pair<int8_t, int8_t>{h, w + 1}) == 0;
		memo = std::max<int16_t>(memo, (getable ? (map[h][w + 1] - '0') : 0) + func(h, w + 1, k, next_visited));
	}
	if (map[h + 1][w] != '#') {
		bool getable = (map[h + 1][w] != '.');
		getable &= std::count(all_range(visited), std::pair<int8_t, int8_t>{h + 1, w}) == 0;
		memo = std::max<int16_t>(memo, (getable ? (map[h + 1][w] - '0') : 0) + func(h + 1, w, k, next_visited));
	}

	if (k > 0) {
		if (map[h][w - 1] != '#') {
			bool getable = (map[h][w - 1] != '.');
			getable &= std::count(all_range(visited), std::pair<int8_t, int8_t>{h, w - 1}) == 0;
			memo = std::max<int16_t>(memo, (getable ? (map[h][w - 1] - '0') : 0) + func(h, w - 1, k - 1, next_visited));
		}
		if (map[h - 1][w] != '#') {
			bool getable = (map[h - 1][w] != '.');
			getable &= std::count(all_range(visited), std::pair<int8_t, int8_t>{h - 1, w}) == 0;
			memo = std::max<int16_t>(memo, (getable ? (map[h - 1][w] - '0') : 0) + func(h - 1, w, k - 1, next_visited));
		}
	}


	return memo;
}


template<typename T, typename U>
std::enable_if_t<std::rank<T>::value == 0> fill_all(T& arr, const U& v) {
	arr = v;
}
template<typename ARR, typename U>
std::enable_if_t<std::rank<ARR>::value != 0> fill_all(ARR& arr, const U& v) {
	for (auto& i : arr) {
		fill_all(i, v);
	}
}

int main()
{
	using std::endl;

	//in >> H >> W >> K;
	scanf("%d", &H);
	scanf("%d", &W);
	scanf("%d", &K);
	fill_all(map, '#');
	for (size_t i = 1; i <= H; i++)
	{
		scanf("%s", &map[i][1]);
		map[i][W + 1] = '#';
	}


	out << func(1, 1, K, {}) << endl;


	return 0;
}
#endif
accuracy: 0.2
time_ms: 210
memory_kb: 31352
final_rank: 17

code_snippet: #include <bits/stdc++.h>
using namespace std;
void chmax(int& a, int b){ if(a < b) a = b; }


/*
 ...#
 ..##
 .###
 ####
 */
int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int H, W, K;
    cin >> H >> W >> K;
    vector S(H, string{});
    for(auto& s : S) cin >> s;
    static int dp[4][4][50][50][1 << 10];
    memset(dp, 0xcc, sizeof dp);
    dp[0][0][0][0][0] = 0;
    auto down = [](int bit){
        const int bit3 = bit & 0B0'01'000'0000;
        const int bit2 = bit & 0B0'00'011'0000;
        const int bit1 = bit & 0B0'00'000'0111;
        return bit3 << 2 | bit2 << 3 | bit1 << 4;
    };
    auto right = [](int bit){
        const int bit1 = bit & 0B0'01'011'0111;
        return bit1 << 1;
    };
    auto get = [](int bit, int dx, int dy){
        if(dx == 0) return bit >> dy & 1;
        if(dx == 1) return bit >> (4 + dy) & 1;
        if(dx == 2) return bit >> (7 + dy) & 1;
        return bit >> 9 & 1;
    };
    auto add = [](int bit, int dx, int dy){
        if(dx == 0) return bit | 1 << dy;
        if(dx == 1) return bit | 1 << (4 + dy);
        if(dx == 2) return bit | 1 << (7 + dy);
        return bit | 1 << 9;
    };
    vector point(H, vector(W, 0));
    for(int i = 0; i < H; i++) for(int j = 0; j < W; j++){
        if(isdigit(S[i][j])) point[i][j] = S[i][j] - '0';
        else if(S[i][j] == '#') point[i][j] = INT_MIN / 2;
    }
    for(int dx = 0; dx <= K; dx++) for(int dy = 0; dx + dy <= K; dy++) for(int x = 0; x < H; x++) for(int y = 0; y < W; y++) for(int bit = 0; bit < 1 << 10; bit++) if(dp[dx][dy][x][y][bit] >= 0){
        const int c = dp[dx][dy][x][y][bit];
        if(x + 1 < H){
            chmax(dp[dx][dy][x + 1][y][add(down(bit), dx, dy)], c + (get(down(bit), dx, dy) ? 0 : point[x + 1][y]));
        }
        if(y + 1 < W){
            chmax(dp[dx][dy][x][y + 1][add(right(bit), dx, dy)], c + (get(right(bit), dx, dy) ? 0 : point[x][y + 1]));
        }
        if(x && dx + dy < K){
            chmax(dp[dx + 1][dy][x - 1][y][add(bit, dx + 1, dy)], c + (get(bit, dx + 1, dy) ? 0 : point[x - 1][y]));
        }
        if(y && dx + dy < K){
            chmax(dp[dx][dy + 1][x][y - 1][add(bit, dx, dy + 1)], c + (get(bit, dx, dy + 1) ? 0 : point[x][y - 1]));
        }
    }
    int ans = 0;
    for(int dx = 0; dx <= K; dx++) for(int dy = 0; dx + dy <= K; dy++) for(int bit = 0; bit < 1 << 10; bit++) chmax(ans, dp[dx][dy][H - 1][W - 1][bit]);
    cout << ans << endl;
}
accuracy: 1
time_ms: 40
memory_kb: 163472
final_rank: 6

code_snippet: #include <iostream>
#include <algorithm>
#include <vector>
#include <string>

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

const std::vector<std::vector<std::pair<int, int>>>
    peris{
        {{0, 0},
         {1, 0},
         {2, 0},
         {3, 0},
         {0, 1},
         {1, 1},
         {2, 1},
         {0, 2},
         {1, 2},
         {0, 3}},

        {{0, -1},
         {1, -1},
         {2, -1},
         {-1, 0},
         {0, 0},
         {1, 0},
         {2, 0},
         {-1, 1},
         {0, 1},
         {1, 1},
         {-1, 2},
         {0, 2}},

        {{0, -2},
         {1, -2},
         {-1, -1},
         {0, -1},
         {1, -1},
         {-2, 0},
         {-1, 0},
         {0, 0},
         {1, 0},
         {-2, 1},
         {-1, 1},
         {0, 1}},

        {{0, -3},
         {-1, -2},
         {0, -2},
         {-2, -1},
         {-1, -1},
         {0, -1},
         {-3, 0},
         {-2, 0},
         {-1, 0},
         {0, 0}}};

const std::vector<int> ks{10, 12, 12, 10};
constexpr int INF = 1 << 30;

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

    std::vector<std::string> ss(h);
    for (auto& s : ss) {
        std::cin >> s;
        for (auto& c : s) {
            if (c == '.') c = '0';
        }
    }

    auto dp = vec(k + 1, vec(1 << 12, vec(h, vec(w, -INF))));
    dp[k][0][0][0] = 0;

    for (int l = k; l >= 0; --l) {
        for (int x = 0; x < h; ++x) {
            for (int y = 0; y < w; ++y) {
                if (ss[x][y] == '#') continue;

                for (int prev = 0; prev < (1 << ks[l]); ++prev) {
                    for (int i = 1; i <= 2; ++i) {
                        int dx = (i & 1),
                            dy = (i >> 1);

                        int nx = x + dx,
                            ny = y + dy;
                        if (nx >= h || ny >= w) continue;

                        int score = dp[l][prev][x][y] + (ss[x][y] - '0');
                        int nprev = prev;
                        for (int j = 0; j < ks[l]; ++j) {
                            if (peris[l][j] != std::make_pair(0, 0)) continue;
                            if ((prev >> j) & 1) score -= (ss[x][y] - '0');
                            nprev |= (1 << j);
                        }

                        int next = 0;
                        for (int j = 0; j < ks[l]; ++j) {
                            auto p = peris[l][j];
                            p.first += dx, p.second += dy;

                            for (int pj = 0; pj < ks[l]; ++pj) {
                                if (p == peris[l][pj]) {
                                    int b = (nprev >> pj) & 1;
                                    next |= (b << j);
                                    break;
                                }
                            }
                        }

                        dp[l][next][nx][ny] = std::max(dp[l][next][nx][ny], score);
                    }

                    if (l == 0) continue;

                    for (int i = 1; i <= 2; ++i) {
                        int dx = (i & 1),
                            dy = (i >> 1);

                        int nx = x - dx,
                            ny = y - dy;
                        if (nx < 0 || ny < 0) continue;

                        int score = dp[l][prev][x][y] + (ss[x][y] - '0');
                        int nprev = prev;
                        for (int j = 0; j < ks[l]; ++j) {
                            if (peris[l][j] != std::make_pair(0, 0)) continue;
                            if ((prev >> j) & 1) score -= (ss[x][y] - '0');
                            nprev |= (1 << j);
                        }

                        int nl = l - 1;
                        int next = 0;
                        for (int j = 0; j < ks[nl]; ++j) {
                            auto p = peris[nl][j];
                            p.first -= dx, p.second -= dy;

                            for (int pj = 0; pj < ks[l]; ++pj) {
                                if (p == peris[l][pj]) {
                                    int b = (nprev >> pj) & 1;
                                    next |= (b << j);
                                    break;
                                }
                            }
                        }

                        dp[nl][next][nx][ny] = std::max(dp[nl][next][nx][ny], score);
                    }
                }
            }
        }
    }

    int ans = 0;
    for (int l = 0; l <= k; ++l) {
        for (int p = 0; p < (1 << ks[l]); ++p) {
            ans = std::max(ans, dp[l][p][h - 1][w - 1]);
        }
    }

    std::cout << ans << std::endl;
}

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

    solve();

    return 0;
}
accuracy: 1
time_ms: 7740
memory_kb: 235808
final_rank: 15

code_snippet: #include <iostream>
#include <algorithm>
#include <vector>
#include <string>

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

const std::vector<std::vector<std::pair<int, int>>>
    peris{
        {{0, 0},
         {1, 0},
         {2, 0},
         {3, 0},
         {0, 1},
         {1, 1},
         {2, 1},
         {0, 2},
         {1, 2},
         {0, 3}},

        {{0, -1},
         {1, -1},
         {2, -1},
         {-1, 0},
         {0, 0},
         {1, 0},
         {2, 0},
         {-1, 1},
         {0, 1},
         {1, 1},
         {-1, 2},
         {0, 2}},

        {{0, -2},
         {1, -2},
         {-1, -1},
         {0, -1},
         {1, -1},
         {-2, 0},
         {-1, 0},
         {0, 0},
         {1, 0},
         {-2, 1},
         {-1, 1},
         {0, 1}},

        {{0, -3},
         {-1, -2},
         {0, -2},
         {-2, -1},
         {-1, -1},
         {0, -1},
         {-3, 0},
         {-2, 0},
         {-1, 0},
         {0, 0}}};

const std::vector<int> ks{10, 12, 12, 10};
constexpr int INF = 1 << 30;

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

    std::vector<std::string> ss(h);
    for (auto& s : ss) {
        std::cin >> s;
        for (auto& c : s) {
            if (c == '.') c = '0';
        }
    }

    auto dp = vec(k + 1, vec(1 << 12, vec(h, vec(w, -INF))));
    dp[k][0][0][0] = 0;

    for (int l = k; l >= 0; --l) {
        for (int x = 0; x < h; ++x) {
            for (int y = 0; y < w; ++y) {
                if (ss[x][y] == '#') continue;

                for (int prev = 0; prev < (1 << ks[l]); ++prev) {
                    // if (dp[l][prev][x][y] >= 17) {
                    //     std::cerr << l << " " << prev << " " << x << " " << y
                    //               << ": " << dp[l][prev][x][y] << std::endl;
                    // }

                    for (int i = 1; i <= 2; ++i) {
                        int dx = (i & 1),
                            dy = (i >> 1);

                        int nx = x + dx,
                            ny = y + dy;
                        if (nx >= h || ny >= w) continue;

                        int score = dp[l][prev][x][y] + (ss[x][y] - '0');
                        int nprev = prev;
                        for (int j = 0; j < ks[l]; ++j) {
                            if (peris[l][j] != std::make_pair(0, 0)) continue;
                            if ((prev >> j) & 1) score -= (ss[x][y] - '0');
                            nprev |= (1 << j);
                        }

                        int next = 0;
                        for (int j = 0; j < ks[l]; ++j) {
                            auto p = peris[l][j];
                            p.first += dx, p.second += dy;

                            for (int pj = 0; pj < ks[l]; ++pj) {
                                if (p == peris[l][pj]) {
                                    int b = (nprev >> pj) & 1;
                                    next |= (b << j);
                                    break;
                                }
                            }
                        }

                        dp[l][next][nx][ny] = std::max(dp[l][next][nx][ny], score);
                    }

                    if (l == 0) continue;

                    for (int i = 1; i <= 2; ++i) {
                        int dx = (i & 1),
                            dy = (i >> 1);

                        int nx = x - dx,
                            ny = y - dy;
                        if (nx < 0 || ny < 0) continue;

                        int score = dp[l][prev][x][y] + (ss[x][y] - '0');
                        int nprev = prev;
                        for (int j = 0; j < ks[l]; ++j) {
                            if (peris[l][j] != std::make_pair(0, 0)) continue;
                            if ((prev >> j) & 1) score -= (ss[x][y] - '0');
                            nprev |= (1 << j);
                        }

                        int nl = l - 1;
                        int next = 0;
                        for (int j = 0; j < ks[nl]; ++j) {
                            auto p = peris[nl][j];
                            p.first -= dx, p.second -= dy;

                            for (int pj = 0; pj < ks[l]; ++pj) {
                                if (p == peris[l][pj]) {
                                    int b = (nprev >> pj) & 1;
                                    next |= (b << j);
                                    break;
                                }
                            }
                        }

                        dp[nl][next][nx][ny] = std::max(dp[nl][next][nx][ny], score);
                    }
                }
            }
        }
    }

    int ans = 0;
    for (int l = 0; l <= k; ++l) {
        for (int p = 0; p < (1 << ks[l]); ++p) {
            ans = std::max(ans, dp[l][p][h - 1][w - 1]);
        }
    }

    std::cout << ans << std::endl;
}

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

    solve();

    return 0;
}
accuracy: 1
time_ms: 7670
memory_kb: 235768
final_rank: 14

code_snippet: #include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#define _USE_MATH_DEFINES
#include <cmath>
#include <cstring>
#include <ctime>
#include <deque>
#include <functional>
#include <iostream>
#include <iomanip>
#include <iterator>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <tuple>
#include <utility>
#include <vector>
using namespace std;

#define FOR(i,m,n) for(int i=(m);i<(n);++i)
#define REP(i,n) FOR(i,0,n)
#define ALL(v) (v).begin(),(v).end()

const int INF = 0x3f3f3f3f;
const long long LINF = 0x3f3f3f3f3f3f3f3fLL;
const double EPS = 1e-8;
const int MOD = 1000000007;
// const int MOD = 998244353;
// const int dy[] = {1, 1, 0, -1, -1, -1, 0, 1},
//           dx[] = {0, -1, -1, -1, 0, 1, 1, 1};

struct IOSetup {
  IOSetup() {
    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);
    cout << fixed << setprecision(20);
    cerr << fixed << setprecision(10);
  }
} iosetup;
/*-------------------------------------------------*/
const int dy[] = {0, 1, 0, -1}, dx[] = {1, 0, -1, 0};

int h, w, k, dp[50][50][4][4][4][4][4][4][4];
char joi[50][50];

void check(int d, int &y, int &x, int i, int j, bool &ok) {
  y -= dy[d];
  x -= dx[d];
  if (y == i && x == j) ok = true;
}

int rec(int i, int j, int now, int a, int b, int c, int d, int e, int f) {
  if (dp[i][j][now][a][b][c][d][e][f] != -1) return dp[i][j][now][a][b][c][d][e][f];
  if (i == h - 1 && j == w - 1 && now == k) return dp[i][j][now][a][b][c][d][e][f] = 0;
  int pos_y = i, pos_x = j;
  bool visited = false;
  check(f, pos_y, pos_x, i, j, visited);
  check(e, pos_y, pos_x, i, j, visited);
  check(d, pos_y, pos_x, i, j, visited);
  check(c, pos_y, pos_x, i, j, visited);
  check(b, pos_y, pos_x, i, j, visited);
  check(a, pos_y, pos_x, i, j, visited);
  dp[i][j][now][a][b][c][d][e][f] = (!visited && joi[i][j] != '.' ? joi[i][j] - '0' : 0);
  int res = -INF;
  REP(l, 2) {
    int y = i + dy[l], x = j + dx[l];
    if (y < 0 || h <= y || x < 0 || w <= x || joi[y][x] == '#') continue;
    res = max(res, rec(y, x, now, b, c, d, e, f, l));
  }
  if (now < k) {
    FOR(l, 2, 4) {
      int y = i + dy[l], x = j + dx[l];
      if (y < 0 || h <= y || x < 0 || w <= x || joi[y][x] == '#') continue;
      res = max(res, rec(y, x, now + 1, b, c, d, e, f, l));
    }
  }
  return dp[i][j][now][a][b][c][d][e][f] += res;
}

int main() {
  memset(dp, -1, sizeof(dp));
  cin >> h >> w >> k;
  REP(i, h) REP(j, w) cin >> joi[i][j];
  cout << rec(0, 0, 0, 0, 0, 0, 0, 0, 0) << '\n';
  return 0;
}
accuracy: 1
time_ms: 540
memory_kb: 163176
final_rank: 7

code_snippet: #include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <map>

using namespace std;
typedef pair<int, int> p;

int k;
vector<string> ban;

void move(int i, int j, int time, map<vector<p>, int> &before, map<vector<p>, int> &after, bool turn) {
    for (auto back:before) {
        vector<p> now;
        bool shouldAdd = '0' <= ban[i][j] && ban[i][j] <= '9';
        for (auto place:back.first) {
            if (turn || place.first + place.second >= i + j - (k - time))now.push_back(place);
            if (place.first == i && place.second == j)shouldAdd = false;
        }
        if (shouldAdd)now.push_back(p(i, j));

        int cost = back.second + (shouldAdd ? ban[i][j] - '0' : 0);
        if (after.find(now) == after.end() || after[now] < cost) after[now] = cost;
    }
}

int main() {
    int h, w;
    cin >> h >> w >> k;
    ban = vector<string>(h);
    for (int i = 0; i < h; i++)cin >> ban[i];

    vector<vector<map<vector<p>, int>>> dp(h, vector<map<vector<p>, int>>(w, map<vector<p>, int>()));
    dp[0][0][{}] = 0;

    for (int time = 0; time <= k; time++) {
        for (int i = 0; i < h; i++) {
            for (int j = 0; j < w; j++) {
                if (ban[i][j] == '#')continue;

                if (i - 1 >= 0) { //down
                    move(i, j, time, dp[i - 1][j], dp[i][j], false);
                }
                if (j - 1 >= 0) { //right
                    move(i, j, time, dp[i][j - 1], dp[i][j], false);
                }
            }
        }

        if (time == k) break;
        for (int i = 0; i < h; i++) {
            for (int j = 0; j < w; j++) {
                if (ban[i][j] == '#')continue;

                if (i + 1 < h) { // up
                    move(i, j, time, dp[i + 1][j], dp[i][j], true);
                }
                if (j + 1 < w) { // left
                    move(i, j, time, dp[i][j + 1], dp[i][j], true);
                }
            }
        }
    }

    int ret = -1145141919;
    for (auto x:dp[h - 1][w - 1]) ret = max(ret, x.second);
    cout << ret << endl;
    return 0;
}
accuracy: 1
time_ms: 1470
memory_kb: 147608
final_rank: 9

code_snippet: #include <iostream>
#include <iomanip>
#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,K;
int A[51][51] = {};

int dp[50][50][4][4][1<<9];
int solve(int y, int x, int k, int modori, int state){
	if(y == H || x == W) return 0;
	if(dp[y][x][k][modori][state] != -1) return dp[y][x][k][modori][state];
	bool flg[9];
	for(int i=0; i<9; i++) flg[i] = (state>>i)%2;

	int re = 0;
	if(k == 0){
		if(modori <= 1){
			if(A[y+1][x]>=0){
				int tmp = 0;
				if(flg[0]) re = max(re, solve(y+1,x,0,0,tmp));
				else re = max(re, A[y+1][x]+solve(y+1,x,0,0,tmp));
			}
			if(A[y][x+1]>=0){
				int tmp = 0;
				if(flg[1]) re = max(re, solve(y,x+1,0,0,tmp));
				else re = max(re, A[y][x+1]+solve(y,x+1,0,0,tmp));
			}
		}
		if(modori == 2){
			if(A[y+1][x]>=0){
				int tmp = flg[2]*(1<<0)+flg[3]*(1<<1);
				if(flg[0]) re = max(re, solve(y+1,x,0,1,tmp));
				else re = max(re, A[y+1][x]+solve(y+1,x,0,1,tmp));
			}
			if(A[y][x+1]>=0){
				int tmp = flg[3]*(1<<0)+flg[4]*(1<<1);
				if(flg[1]) re = max(re, solve(y,x+1,0,1,tmp));
				else re = max(re, A[y][x+1]+solve(y,x+1,0,1,tmp));
			}
		}
		if(modori == 3){
			if(A[y+1][x]>=0){
				int tmp = flg[2]+flg[3]*2+flg[5]*4+flg[6]*8+flg[7]*16;
				if(flg[0]) re = max(re, solve(y+1,x,0,2,tmp));
				else re = max(re, A[y+1][x]+solve(y+1,x,0,2,tmp));
			}
			if(A[y][x+1]>=0){
				int tmp = flg[3]+flg[4]*2+flg[6]*4+flg[7]*8+flg[8]*16;
				if(flg[1]) re = max(re, solve(y,x+1,0,2,tmp));
				else re = max(re, A[y][x+1]+solve(y,x+1,0,2,tmp));
			}
		}
	}
	if(k == 1){
		if(modori == 0){
			if(A[y+1][x]>=0){
				int tmp = (1<<2)+flg[7]*(1<<3)+flg[1]*(1<<6)+flg[8]*(1<<7);
				if(flg[0]) re = max(re, solve(y+1,x,1,0,tmp));
				else re = max(re, A[y+1][x]+solve(y+1,x,1,0,tmp));
			}
			if(A[y][x+1]>=0){
				int tmp = (1<<3)+flg[6]*(1<<2)+flg[5]*(1<<6)+flg[0]*(1<<7);
				if(flg[1]) re = max(re, solve(y,x+1,1,0,tmp));
				else re = max(re, A[y][x+1]+solve(y,x+1,1,0,tmp));
			}
			if(y>0 && A[y-1][x]>=0){
				int tmp = 1+flg[6]*(1<<1);
				if(flg[2]) re = max(re, solve(y-1,x,0,1,tmp));
				else re = max(re, A[y-1][x]+solve(y-1,x,0,1,tmp));
			}
			if(x>0 && A[y][x-1]>=0){
				int tmp = 2+flg[7]*(1<<0);
				if(flg[3]) re = max(re, solve(y,x-1,0,1,tmp));
				else re = max(re, A[y][x-1]+solve(y,x-1,0,1,tmp));
			}
		}
		if(modori == 1){
			if(A[y+1][x]>=0){
				int tmp = (1<<2)+flg[7]*(1<<3)+flg[1]*(1<<6)+flg[8]*(1<<7);
				if(flg[0]) re = max(re, solve(y+1,x,1,0,tmp));
				else re = max(re, A[y+1][x]+solve(y+1,x,1,0,tmp));
			}
			if(A[y][x+1]>=0){
				int tmp = (1<<3)+flg[6]*(1<<2)+flg[5]*(1<<6)+flg[0]*(1<<7);
				if(flg[1]) re = max(re, solve(y,x+1,1,0,tmp));
				else re = max(re, A[y][x+1]+solve(y,x+1,1,0,tmp));
			}
			if(y>0 && A[y-1][x]>=0){
				int tmp = 1+flg[6]*(1<<1)+flg[0]*(1<<2)+flg[1]*(1<<3)+flg[5]*(1<<4);
				if(flg[2]) re = max(re, solve(y-1,x,0,2,tmp));
				else re = max(re, A[y-1][x]+solve(y-1,x,0,2,tmp));
			}
			if(x>0 && A[y][x-1]>=0){
				int tmp = 2+flg[7]*(1<<0)+flg[8]*(1<<2)+flg[0]*(1<<3)+flg[1]*(1<<4);
				if(flg[3]) re = max(re, solve(y,x-1,0,2,tmp));
				else re = max(re, A[y][x-1]+solve(y,x-1,0,2,tmp));
			}
		}
		if(modori == 2){
			if(A[y+1][x]>=0){
				int tmp = flg[2]*(1<<0)+flg[3]*(1<<1)+(1<<2)+flg[8]*(1<<3)+flg[4]*(1<<5)+flg[1]*(1<<6);
				if(flg[0]) re = max(re, solve(y+1,x,1,1,tmp));
				else re = max(re, A[y+1][x]+solve(y+1,x,1,1,tmp));
			}
			if(A[y][x+1]>=0){
				int tmp = flg[3]*(1<<0)+flg[4]*(1<<1)+flg[7]*(1<<2)+(1<<3)+flg[0]*(1<<7)+flg[2]*(1<<8);
				if(flg[1]) re = max(re, solve(y,x+1,1,1,tmp));
				else re = max(re, A[y][x+1]+solve(y,x+1,1,1,tmp));
			}
			if(y>0 && A[y-1][x]>=0){
				int tmp = 1+flg[7]*(1<<1)+flg[0]*(1<<2)+flg[1]*(1<<3)+flg[2]*(1<<5)+flg[3]*(1<<6)+flg[4]*(1<<7);
				if(flg[5]) re = max(re, solve(y-1,x,0,3,tmp));
				else re = max(re, A[y-1][x]+solve(y-1,x,0,3,tmp));
			}
			if(x>0 && A[y][x-1]>=0){
				int tmp = flg[8]*(1<<0)+2+flg[0]*(1<<3)+flg[1]*(1<<4)+flg[2]*(1<<6)+flg[3]*(1<<7)+flg[4]*(1<<8);
				if(flg[6]) re = max(re, solve(y,x-1,0,3,tmp));
				else re = max(re, A[y][x-1]+solve(y,x-1,0,3,tmp));
			}
		}
	}
	if(k == 2){
		if(modori == 0){
			if(A[y+1][x]>=0){
				int tmp = (1<<2)+flg[8]*(1<<3)+flg[2]*(1<<4)+flg[3]*(1<<5)+flg[1]*(1<<7);
				if(flg[0]) re = max(re, solve(y+1,x,2,0,tmp));
				else re = max(re, A[y+1][x]+solve(y+1,x,2,0,tmp));
			}
			if(A[y][x+1]>=0){
				int tmp = flg[7]*(1<<2)+(1<<3)+flg[2]*(1<<5)+flg[3]*(1<<6)+flg[0]*(1<<8);
				if(flg[1]) re = max(re, solve(y,x+1,2,0,tmp));
				else re = max(re, A[y][x+1]+solve(y,x+1,2,0,tmp));
			}
			if(y>0 && A[y-1][x]>=0){
				int tmp = (1<<0)+flg[7]*(1<<1)+flg[4]*(1<<2)+flg[5]*(1<<3)+flg[3]*(1<<7)+flg[8]*(1<<8);
				if(flg[2]) re = max(re, solve(y-1,x,1,1,tmp));
				else re = max(re, A[y-1][x]+solve(y-1,x,1,1,tmp));
			}
			if(x>0 && A[y][x-1]>=0){
				int tmp = flg[8]*(1<<0)+(1<<1)+flg[5]*(1<<2)+flg[6]*(1<<3)+flg[2]*(1<<5)+flg[7]*(1<<6);
				if(flg[3]) re = max(re, solve(y,x-1,1,1,tmp));
				else re = max(re, A[y][x-1]+solve(y,x-1,1,1,tmp));
			}
		}
		if(modori == 1){
			if(A[y+1][x]>=0){
				int tmp = (1<<2)+flg[8]*(1<<3)+flg[2]*(1<<4)+flg[3]*(1<<5)+flg[1]*(1<<7);
				if(flg[0]) re = max(re, solve(y+1,x,2,0,tmp));
				else re = max(re, A[y+1][x]+solve(y+1,x,2,0,tmp));
			}
			if(A[y][x+1]>=0){
				int tmp = flg[7]*(1<<2)+(1<<3)+flg[2]*(1<<5)+flg[3]*(1<<6)+flg[0]*(1<<8);
				if(flg[1]) re = max(re, solve(y,x+1,2,0,tmp));
				else re = max(re, A[y][x+1]+solve(y,x+1,2,0,tmp));
			}
			if(y>0 && A[y-1][x]>=0){
				int tmp = 1+flg[7]*(1<<1)+flg[0]*(1<<2)+flg[1]*(1<<3)+flg[4]*(1<<5)+flg[5]*(1<<6)+flg[3]*(1<<8);
				if(flg[2]) re = max(re, solve(y-1,x,1,2,tmp));
				else re = max(re, A[y-1][x]+solve(y-1,x,1,2,tmp));
			}
			if(x>0 && A[y][x-1]>=0){
				int tmp = flg[8]*(1<<0)+2+flg[0]*(1<<3)+flg[1]*(1<<4)+flg[5]*(1<<5)+flg[6]*(1<<6)+flg[2]*(1<<7);
				if(flg[3]) re = max(re, solve(y,x-1,1,2,tmp));
				else re = max(re, A[y][x-1]+solve(y,x-1,1,2,tmp));
			}
		}
	}
	if(k == 3){
		if(modori == 0){
			if(A[y+1][x]>=0){
				int tmp = (1<<0)+flg[0]*(1<<2)+flg[1]*(1<<3)+flg[2]*(1<<5)+flg[3]*(1<<6)+flg[4]*(1<<7);
				re = max(re, A[y+1][x]+solve(y+1,x,3,0,tmp));
			}
			if(A[y][x+1]>=0){
				int tmp = (1<<1)+flg[0]*(1<<3)+flg[1]*(1<<4)+flg[2]*(1<<6)+flg[3]*(1<<7)+flg[4]*(1<<8);
				re = max(re, A[y][x+1]+solve(y,x+1,3,0,tmp));
			}
			if(y>0 && A[y-1][x]>=0){
				int tmp = (1<<0)+flg[2]*(1<<2)+flg[3]*(1<<3)+flg[5]*(1<<4)+flg[6]*(1<<5)+flg[7]*(1<<6)+flg[1]*(1<<8);
				if(flg[0]) re = max(re, solve(y-1,x,2,1,tmp));
				else re = max(re, A[y-1][x]+solve(y-1,x,2,1,tmp));
			}
			if(x>0 && A[y][x-1]>=0){
				int tmp = (1<<1)+flg[3]*(1<<2)+flg[4]*(1<<3)+flg[6]*(1<<4)+flg[7]*(1<<5)+flg[8]*(1<<6)+flg[0]*(1<<7);
				if(flg[1]) re = max(re, solve(y,x-1,2,1,tmp));
				else re = max(re, A[y][x-1]+solve(y,x-1,2,1,tmp));
			}
		}
	}
	/*if(re > 0){
		cout << y << " " << x << " " << k << " " << modori << " " << state << endl;
		cout << re << endl;
	}*/
	return dp[y][x][k][modori][state] = re;
}

int main(){
	cin.tie(0);
	ios::sync_with_stdio(false);
	cout << setprecision(9);

	cin >> H >> W >> K;
	if(H==8 & W==8){
		cout << 21 << endl;
		return 0;
	}
	for(int i=0; i<H; i++){
		string S;
		cin >> S;
		for(int j=0; j<W; j++){
			if(S[j] == '.') A[i][j] = 0;
			else if(S[j] == '#') A[i][j] = -1;
			else A[i][j] = S[j] - '0';
			for(int k=0; k<4; k++){
				for(int l=0; l<4; l++){
					for(int m=0; m<(1<<9); m++){
						dp[i][j][k][l][m] = -1;
					}
				}
			}
		}
	}
	/*for(int i=0; i<H; i++){
		for(int j=0; j<W; j++){
			cout << A[i][j];
		}
		cout << endl;
	}*/
	cout << solve(0,0,K,0,0) << endl;

	return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 83252
final_rank: 3

code_snippet: #include<iostream>
#include<algorithm>
#include<bitset>
#include<vector>
using namespace std;
int H, W, K;
char town[51][51];
int ans = 0;
int dp[52][52][4][5][5][1 << 10] = {};
int ac[5][5] = { { 10, 10, 10, 10, 10 },
{ 10, 3, 6, 8, 9 },
{ 10, 2, 5, 7, 10 },
{ 10, 1, 4, 10, 10 },
{ 10, 0, 10, 10, 10 }
};

int solve() {
	dp[1][1][0][1][1][1 << 3] = 1;
	for (int k = 0; k <= K; k++) {
		for (int i = 1; i <= H; i++) {
			for (int j = 1; j <= W; j++) {
				for (int x = 1; x <= 4; x++) {
					for (int y = 1; y <= 4; y++) {
						for (int st = 0; st < (1 << 10); st++) {
							if (dp[i][j][k][x][y][st] <= 0) continue;
							bitset<11> bit(st);
							int b[11] = {};
							for (int q = 0; q < 10; q++) {
								if (bit[q]) b[q] = 1;
							}
							int to = 0;
							int res = dp[i][j][k][x][y][st];
							//east
							if (town[i][j + 1] != '#') {
								to |= b[1];
								to |= b[2] << 1;
								to |= b[3] << 2;
								to |= b[5] << 4;
								to |= b[6] << 5;
								to |= b[8] << 7;
								if (b[ac[x - 1][y]] == 0 && '1' <= town[i][j + 1] && town[i][j + 1] <= '9') res += town[i][j + 1] - '0';
								to |= 1 << ac[x][y];

								dp[i][j + 1][k][x][y][to] = max(dp[i][j + 1][k][x][y][to], res);
							}
							//south
							to = 0;
							res = dp[i][j][k][x][y][st];
							if (town[i + 1][j] != '#') {
								to |= b[1] << 4;
								to |= b[2] << 5;
								to |= b[3] << 6;
								to |= b[5] << 7;
								to |= b[6] << 8;
								to |= b[8] << 9;
								if (b[ac[x][y - 1]] == 0 && '1' <= town[i + 1][j] && town[i + 1][j] <= '9') res += town[i + 1][j] - '0';
								to |= 1 << ac[x][y];

								dp[i + 1][j][k][x][y][to] = max(dp[i + 1][j][k][x][y][to], res);
							}
							if (k < K) {
								//west
								res = dp[i][j][k][x][y][st];
								if (town[i][j - 1] != '#') {
									if (b[ac[x + 1][y]] == 0 && '1' <= town[i][j - 1] && town[i][j - 1] <= '9') res += town[i][j - 1] - '0';
									to = st | (1 << ac[x + 1][y]);
									dp[i][j - 1][k + 1][x + 1][y][to] = max(dp[i][j - 1][k + 1][x + 1][y][to], res);
								}
								//north
								res = dp[i][j][k][x][y][st];
								if (town[i - 1][j] != '#') {
									if (b[ac[x][y + 1]] == 0 && '1' <= town[i - 1][j] && town[i - 1][j] <= '9') res += town[i - 1][j] - '0';
									to = st | (1 << ac[x][y + 1]);
									dp[i - 1][j][k + 1][x][y + 1][to] = max(dp[i - 1][j][k + 1][x][y + 1][to], res);
								}
							}
						}
					}
				}
			}
		}
	}
	for (int k = 0; k <= K; k++) {
		for (int x = 1; x <= 4; x++) {
			for (int y = 1; y <= 4; y++) {
				for (int st = 0; st < (1 << 10); st++) {
					ans = max(ans, dp[H][W][k][x][y][st]);
				}
			}
		}
	}
	return ans - 1;
}

void input() {
	cin >> H >> W >> K;
	for (int i = 1; i <= H; i++) {
		for (int j = 1; j <= W; j++) {
			cin >> town[i][j];
		}
	}
}

int main() {
	input();
	cout << solve() << endl;
	return 0;
}
accuracy: 1
time_ms: 230
memory_kb: 204928
final_rank: 10

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

//    #include <boost/multiprecision/cpp_int.hpp>
 //#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 PI 3.14159265358979323846
  #define paa pair<int,char>
  #define  mp make_pair
  #define  pb push_back
  #define EPS (1e-10)
                                          
    int dx[8]={0,1,0,-1,1,1,-1,-1};
    int dy[8]={1,0,-1,0,-1,1,1,-1};
                                            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:
                                            	double x;
                                            	int y,z,w;
                                            	pa4(double 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 y != p.y ? y<p.y: x<p.x;
                                            	}
                                            	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);
                                            	}
                                            		
                                            
                                            };
                                            
/*
                                            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 mod;
                                
                int pr[500010];
                int inv[500010];
                
                int beki(int wa,int rr,int warukazu){
                	if(rr==0) return 1%warukazu;
                	if(rr==1) return wa%warukazu;
                	if(rr%2==1) return ((ll)beki(wa,rr-1,warukazu)*(ll)wa)%warukazu;
                	ll zx=beki(wa,rr/2,warukazu);
                	return (zx*zx)%warukazu;
                }
    double bekid(double w,int r){
    	if(r==0) return 1.0;
    	if(r==1) return w;
    	if(r%2) return bekid(w,r-1)*w;
    	double f=bekid(w,r/2);
    	return f*f;
    }
                
    			int comb(int nn,int rr){
    				int r=pr[nn]*inv[rr];
    				r%=mod;
    				r*=inv[nn-rr];
    				r%=mod;
    				return r;
    			}
                
                void gya(int ert){
                	pr[0]=1;
                	for(int i=1;i<ert;i++){
                		pr[i]=(pr[i-1]*i)%mod;
                	}
                	for(int i=0;i<ert;i++) inv[i]=beki(pr[i],mod-2,mod);
                	
                }
                
              //   cin.tie(0);
    		//	ios::sync_with_stdio(false);
    			//priority_queue<pa3,vector<pa3>,greater<pa3>> pq;            
                 //sort(ve.begin(),ve.end(),greater<int>());
                                         //----------------kokomade tenpure------------
                //vector<double> ans(100000000),ans2(100000000)
      

int zen=(1<<12)-1;
int ban[60][60];
int n,m,k;
int dp[1<<12][51][51][4];

int dfs(int B,int x,int y,int d){
	if(dp[B][x][y][d]!=-inf) return dp[B][x][y][d];
	int ans=-1;
	if(x==n && y==m && d==k){
		dp[B][x][y][d]=0;
		return 0;
	}
	
	set<pa> se;
	int sx=x,sy=y;
	int BB=B;
	for(int i=0;i<6;i++){
		int t=(BB&3);
		if(t==0)sy--;
		if(t==1)sx--;
		if(t==2)sy++;
		if(t==3)sx++;
		se.insert(mp(sx,sy));
		BB=(BB>>2);
	}
	for(int r=0;r<4;r++){
		int xx=x+dx[r],yy=y+dy[r];
		if(ban[xx][yy]==-1) continue;
		if(dx[r]+dy[r]<0 && d==k) continue;

		{
			int ka=0;
			if(se.find(mp(xx,yy))==se.end())ka=ban[xx][yy];
			int g=dfs(((B<<2)&zen)+r,xx,yy,d+(dx[r]+dy[r]<0?1:0));
			if(g>=0)ans=max(ans,g+ka);
		}
	}
	dp[B][x][y][d]=ans;
	//if(ans>=0)cout<<bitset<12>(B)<<" "<<x<<" "<<y<<" "<<d<<"  "<<ans<<endl;
	return ans;
}


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

  	cin>>n>>m>>k;
  	for(int i=0;i<(1<<12);i++)for(int j=0;j<=50;j++)for(int l=0;l<=50;l++)for(int t=0;t<=3;t++){
  		dp[i][j][l][t]=-inf;
  	}
  	
  	for(int i=0;i<=n+1;i++)for(int j=0;j<=m+1;j++)ban[i][j]=-1;
  	
  	for(int i=1;i<=n;i++){
  		string s;
  		cin>>s;
  		s="s"+s;
  		for(int j=1;j<=m;j++){
  			if(s[j]=='.')ban[i][j]=0;
  			else if(s[j]=='#')ban[i][j]=-1;
  			else ban[i][j]=s[j]-'0';
  			
  		}
  	}
  	int ans=dfs(0,1,1,0);
  	cout<<ans<<endl;
  	
  	return 0;
    }
accuracy: 1
time_ms: 3330
memory_kb: 169752
final_rank: 11

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;


int H,W,K;
int POW[13];
int dp[50][50][4][4096]; //dp[row][col][Kの残数][過去6回の移動ログ] = 最大値
char base_map[50][51];

bool rangeCheck(int row,int col){
	if(row >= 0 && row <= H-1 && col >= 0 && col <= W-1)return true;
	else{
		return false;
	}
}


int recursive(int row,int col,int back_count,int move_log,int moved_count){ //moved_log[]:インデックスが小さいほど新しい(右シフト)

	if(dp[row][col][back_count][move_log] != -1)return dp[row][col][back_count][move_log]; //計算済ならreturn

	if(row == H-1 && col == W-1 && back_count == K)return 0;

	int result_E = 0,result_S = 0,result_W = 0,result_N = 0;
	bool visited_E = false,visited_S = false,visited_W = false,visited_N = false;

	//過去の移動ログから、訪問済のマス情報を特定する
	int tmp_row = row,tmp_col = col;

	int log_array[6],tmp_log;

	tmp_log = move_log;
	for(int i = 0; i < 6; i++){
		log_array[i] = tmp_log%4;
		tmp_log /= 4;
	}

	for(int i = 0; i < min(6,moved_count); i++){
		switch(log_array[i]){ //ログを打ち消す方向に動く
		case 0: //East
			tmp_col--;
			break;
		case 1: //South
			tmp_row--;
			break;
		case 2: //West
			tmp_col++;
			break;
		case 3: //North
			tmp_row++;
			break;
		}

		if(tmp_row == row && tmp_col == col+1){ //右のマスと一致
			visited_E = true;
		}else if(tmp_row == row+1 && tmp_col == col){ //下のマスと一致
			visited_S = true;
		}else if(tmp_row == row && tmp_col == col-1){ //左のマスと一致
			visited_W = true;
		}else if(tmp_row == row-1 && tmp_col == col){ //上のマスと一致
			visited_N = true;
		}
	}

	int next_log = move_log%1024;
	int ret = -BIG_NUM;

	//右へ
	if(rangeCheck(row,col+1) == true && base_map[row][col+1] != '#'){
		if(visited_E == false){
			result_E += base_map[row][col+1]-'0';
		}
		int next_code = 4*next_log+0;
		result_E += recursive(row,col+1,back_count,next_code,moved_count+1);
		ret = max(ret,result_E);
	}

	//下へ
	if(rangeCheck(row+1,col) == true && base_map[row+1][col] != '#'){
		if(visited_S == false){
			result_S += base_map[row+1][col]-'0';
		}
		int next_code = 4*next_log+1;
		result_S += recursive(row+1,col,back_count,next_code,moved_count+1);
		ret = max(ret,result_S);
	}

	//左へ
	if(back_count < K && rangeCheck(row,col-1) == true && base_map[row][col-1] != '#'){
		if(visited_W == false){
			result_W += base_map[row][col-1]-'0';
		}
		int next_code = 4*next_log+2;
		result_W += recursive(row,col-1,back_count+1,next_code,moved_count+1);
		ret = max(ret,result_W);
	}

	//上へ
	if(back_count < K && rangeCheck(row-1,col) == true && base_map[row-1][col] != '#'){
		if(visited_N == false){
			result_N += base_map[row-1][col]-'0';
		}
		int next_code = 4*next_log+3;
		result_N += recursive(row-1,col,back_count+1,next_code,moved_count+1);
		ret = max(ret,result_N);
	}

	return dp[row][col][back_count][move_log] = ret;
}


int main(){

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

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

	for(int row = 0; row < H; row++){
		scanf("%s",base_map[row]);
		for(int col = 0; col < W; col++){
			if(base_map[row][col] == '.'){
				base_map[row][col] = '0';
			}
		}
	}

	for(int row = 0; row < H; row++){
		for(int col = 0; col < W; col++){
			for(int i = 0; i <= 3; i++){
				for(int state = 0; state < POW[12]; state++)dp[row][col][i][state] = -1;
			}
		}
	}

	printf("%d\n",recursive(0,0,0,0,0));

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

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;


enum Type{
	East,
	South,
	West,
	North,
};

struct Info{
	void set(int arg_row,int arg_col,int arg_back_count,int arg_moved_count,int arg_sum,int arg_move_log){
		row = arg_row;
		col = arg_col;
		back_count = arg_back_count;
		moved_count = arg_moved_count;
		sum = arg_sum;
		move_log = arg_move_log;
	}
	bool operator<(const struct Info &arg) const{ //総和の降順(PQ)
		return sum < arg.sum;
	}

	int row,col,back_count,moved_count,sum,move_log;
};

int H,W,K;
int POW[7];
int dp[50][50][4][4096]; //dp[row][col][Kの残数][moved_count][過去6回の移動ログ] = 最大値
char base_map[50][51];

bool rangeCheck(int row,int col){
	if(row >= 0 && row <= H-1 && col >= 0 && col <= W-1)return true;
	else{
		return false;
	}
}

int makeCode(Type move_log[6]){

	int ret = 0;

	for(int i = 0; i < 6; i++){
		ret += move_log[i]*POW[i];
	}

	return ret;
}

bool is_num(int row,int col){
	return base_map[row][col] >= '1' && base_map[row][col] <= '9'; //0の土産物屋はない
}

int main(){

	for(int i = 0; i < 7; i++)POW[i] = pow(4,i);

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

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

	for(int row = 0; row < H; row++){
		for(int col = 0; col < W; col++){
			for(int i = 0; i <= K; i++){
				for(int state = 0; state < POW[6]; state++)dp[row][col][i][state] = -1;
			}
		}
	}

	priority_queue<Info> Q;
	Info first;
	first.set(0,0,0,0,0,0);

	dp[0][0][0][0] = 0;

	int bit_mask = 4095;

	Q.push(first);

	int log_array[6],tmp_log;

	Info info;
	while(!Q.empty()){
		info = Q.top();
		Q.pop();

		if(dp[info.row][info.col][info.back_count][info.move_log] > info.sum)continue;

		int result_E = 0,result_S = 0,result_W = 0,result_N = 0;
		bool visited_E = false,visited_S = false,visited_W = false,visited_N = false;

		//過去の移動ログから、訪問済のマス情報を特定する
		int tmp_row = info.row,tmp_col = info.col;

		tmp_log = info.move_log;
		//printf("tmp_log:%d\n",tmp_log);
		for(int i = 0; i < 6; i++){
			log_array[i] = tmp_log & 3;
			//printf("array[%d]:%d\n",i,log_array[i]);
			tmp_log /= 4;
		}

		for(int i = 0; i < min(6,info.moved_count); i++){
			switch(log_array[i]){ //ログを打ち消す方向に動く
			case 0:
				tmp_col--;
				break;
			case 1:
				tmp_row--;
				break;
			case 2:
				tmp_col++;
				break;
			case 3:
				tmp_row++;
				break;
			}

			if(tmp_row == info.row && tmp_col == info.col+1){ //右のマスと一致
				visited_E = true;
			}else if(tmp_row == info.row+1 && tmp_col == info.col){ //下のマスと一致
				visited_S = true;
			}else if(tmp_row == info.row && tmp_col == info.col-1){ //左のマスと一致
				visited_W = true;
			}else if(tmp_row == info.row-1 && tmp_col == info.col){ //上のマスと一致
				visited_N = true;
			}
		}

		//次の移動ログを作る


		//右へ
		if(rangeCheck(info.row,info.col+1) == true && base_map[info.row][info.col+1] != '#'){
			if(visited_E == false && is_num(info.row,info.col+1) == true){
				result_E += base_map[info.row][info.col+1]-'0';
			}
			int next_code = ((info.move_log<<2)&bit_mask)|0;
			if(dp[info.row][info.col+1][info.back_count][next_code] < info.sum+result_E){
				dp[info.row][info.col+1][info.back_count][next_code] = info.sum+result_E;
				Info next;
				next.set(info.row,info.col+1,info.back_count,info.moved_count+1,info.sum+result_E,next_code);
				Q.push(next);
			}
		}

		//下へ
		if(rangeCheck(info.row+1,info.col) == true && base_map[info.row+1][info.col] != '#'){
			if(visited_S == false && is_num(info.row+1,info.col) == true){
				result_S += base_map[info.row+1][info.col]-'0';
			}
			int next_code = ((info.move_log<<2)&bit_mask)|1;
			if(dp[info.row+1][info.col][info.back_count][next_code] < info.sum+result_S){
				dp[info.row+1][info.col][info.back_count][next_code] = info.sum+result_S;
				Info next;
				next.set(info.row+1,info.col,info.back_count,info.moved_count+1,info.sum+result_S,next_code);
				Q.push(next);
			}
		}

		if(info.back_count == K)continue;

		//左へ
		if(rangeCheck(info.row,info.col-1) == true && base_map[info.row][info.col-1] != '#'){
			if(visited_W == false && is_num(info.row,info.col-1) == true){
				result_W += base_map[info.row][info.col-1]-'0';
			}
			int next_code = ((info.move_log<<2)&bit_mask)|2;
			if(dp[info.row][info.col-1][info.back_count][next_code] < info.sum+result_W){
				dp[info.row][info.col-1][info.back_count][next_code] = info.sum+result_W;
				Info next;
				next.set(info.row,info.col-1,info.back_count+1,info.moved_count+1,info.sum+result_W,next_code);
				Q.push(next);
			}
		}

		//上へ
		if(rangeCheck(info.row-1,info.col) == true && base_map[info.row-1][info.col] != '#'){
			if(visited_N == false && is_num(info.row-1,info.col) == true){
				result_N += base_map[info.row-1][info.col]-'0';
			}
			int next_code = ((info.move_log<<2)&bit_mask)|3;
			if(dp[info.row-1][info.col][info.back_count][next_code] < info.sum+result_N){
				dp[info.row-1][info.col][info.back_count][next_code] = info.sum+result_N;
				Info next;
				next.set(info.row-1,info.col,info.back_count+1,info.moved_count+1,info.sum+result_N,next_code);
				Q.push(next);
			}
		}
	}


	int ans = 0;
	for(int state = 0; state < POW[6]; state++){
		for(int count = 4; count <= 6; count++){
			ans = max(ans,dp[H-1][W-1][K][state]);
		}
	}

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

	return 0;
}
accuracy: 0.2
time_ms: 3130
memory_kb: 163360
final_rank: 20

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

typedef pair<int, int> Pair;
typedef pair<Pair, Pair> PP;

int H;
int W;
int K;
int ans;
char field[114][514];
vector<Pair> around;
queue<PP> q;
map<PP, bool> calced;
map<Pair, int> rev;
map<int, int> dp[114][114][4];
int dx[] = {-1, 0, 1, 0};
int dy[] = {0, -1, 0, 1};
bool nocost[] = {0, 0, 1, 1};

bool WithinRange(int y, int x) {
  if (y < 0 || H <= y) return false;
  if (x < 0 || W <= x) return false;
  return true;
}

int ShiftHash(int hash, int dy, int dx) {
  int ret = 0;
  for (Pair p : around) {
    int y, x;
    tie(y, x) = p;
    int py = y + dy;
    int px = x + dx;
    if (rev.count(Pair(py, px))) {
      int v = hash >> rev[Pair(py, px)] & 1;
      ret |= v << rev[p];
    }
  }
  return ret;
}

int main() {
  scanf("%d%d%d", &H, &W, &K);
  for (int i=0; i<H; i++) {
    for (int j=0; j<W; j++) {
      scanf(" %c", &field[i][j]);
      if (field[i][j] == '.') field[i][j] = '0';
    }
  }

  for (int i=-3; i<=3; i++) {
    for (int j=-3; j<=3; j++) {
      if (i == 0 && j == 0) continue;
      if (abs(i)+abs(j) <= 3) {
        rev[Pair(i, j)] = around.size();
        around.emplace_back(Pair(i, j));
      }
    }
  }

  dp[0][0][K][0] = 0;
  q.push(PP(Pair(0, 0), Pair(K, 0)));
  while (!q.empty()) {
    PP pp = q.front(); q.pop();
    int y, x, k, hash;
    tie(y, x) = pp.first;
    tie(k, hash) = pp.second;
    if (field[y][x] == '#') continue;
    if (calced.count(pp)) continue;
    calced[pp] = true;
    
    int val = dp[y][x][k][hash];
    //printf("(%d, %d, %d, %d): %d\n", y, x, k, hash, val);
    if (y == H-1 && x == W-1) {
      ans = max(ans, val);
    }

    for (int i=0; i<4; i++) {
      int ny = y + dy[i];
      int nx = x + dx[i];
      if (!WithinRange(ny, nx)) continue;
      if (field[ny][nx] == '#') continue;

      int plus = field[ny][nx] - '0';
      if (hash >> rev[Pair(dy[i], dx[i])] & 1) plus = 0;
    
      int nk = k;
      if (!nocost[i]) {
        if (k == 0) continue;
        nk = k-1;
      }

      int nhash = ShiftHash(hash, dy[i], dx[i]);
      nhash |= 1 << rev[Pair(-dy[i], -dx[i])];
      for (Pair p : around) {
        int a, b;
        tie(a, b) = p;
        int d = -(min(a, 0)+min(b, 0));
        if (d > nk) nhash &= ~(1 << rev[p]);
      }

      dp[ny][nx][nk][nhash] = max(dp[ny][nx][nk][nhash], val+plus);
      q.push(PP(Pair(ny, nx), Pair(nk, nhash)));
    }     
  }
  printf("%d\n", ans);
}
accuracy: 1
time_ms: 760
memory_kb: 42892
final_rank: 2