Problem:
Route Calculator
You have a grid with $H$ rows and $W$ columns. $H + W$ is even. We denote the cell at the $i$-th row from the top and the $j$-th column from the left by ($i, j$). In any cell ($i, j$), an integer between $1$ and $9$ is written if $i+j$ is even, and either '
+
' or '
*
' is written if $i+j$ is odd.
You can get a mathematical expression by moving right or down $H + W - 2$ times from ($1, 1$) to ($H, W$) and concatenating all the characters written in the cells you passed in order. Your task is to maximize the calculated value of the resulting mathematical expression by choosing an arbitrary path from ($1, 1$) to ($H, W$). If the maximum value is $10^{15}$ or less, print the value. Otherwise, print $-1$.
Input
The input consists of a single test case in the format below.
$H$ $W$
$a_{1,1}$ ... $a_{1,W}$
...
$a_{H,1}$ ... $a_{H,W}$
The first line consists of two $H$ integers and $W$ ($1 \leq H, W \leq 50$). It is guaranteed that $H + W$ is even. The following $H$ lines represent the characters on the grid. $a_{i,j}$ represents the character written in the cell ($i, j$). In any cell ($i, j$), an integer between $1$ and $9$ is written if $i+j$ is even, and either '
+
' or '
*
' is written if $i+1$ is odd.
Output
Print the answer in one line.
Sample Input 1
3 3
1+2
+9*
1*5
Output for Sample Input 1
46
The maximum value is obtained by passing through the following cells: $(1,1), (2,1), (2,2), (2,3), (3,3)$.
Sample Input 2
1 31
9*9*9*9*9*9*9*9*9*9*9*9*9*9*9*9
Output for Sample Input 2
-1
You can obtain $9^{16}$, but it's too large.
Sample Input 3
5 5
2+2+1
+1+1+
1+2+2
+1+1+
1+1+2
Output for Sample Input 3
10
Sample Input 4
9 7
8+9*4*8
*5*2+3+
1*3*2*2
*5*1+9+
1+2*2*2
*3*6*2*
7*7+6*5
*5+7*2+
3+3*6+8
Output for Sample Input 4
86408

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define vl vector<ll>
#define vvl vector<vl>
#define vvvl vector<vvl>
#define vvvvl vector<vvvl>
#define rep(i, n) for (ll i = 0; i < n; ++i)
#define loop(i,m,n) for(ll i=m;i<=n;i++)

int main(){
    ll h,w;
	cin>>h>>w;
	vector<string> a(h);
	rep(i,h)cin>>a[i];

	vector<vector<pair<ll,ll>>> naname(h+w-1);
	rep(i,h)rep(j,w){naname[i+j].push_back({i,j});}

	vvvvl dpk(h,vvvl(w,vvl(h,vl(w,0))));
	rep(i,h)rep(j,w){
		if((i+j)%2==1)continue;
		dpk[i][j][i][j] = 1;

		loop(z,i+j,h+w-2){
			rep(zz,naname[z].size()){
				ll k = naname[z][zz].first;
				ll l = naname[z][zz].second;
				if(k<i||l<j)continue;
				if(a[k][l]=='+')continue;

				//上
				if(k!=i){
					dpk[i][j][k][l]=max(dpk[i][j][k][l],dpk[i][j][k-1][l]);
				}
				//左
				if(l!=j){
					dpk[i][j][k][l]=max(dpk[i][j][k][l],dpk[i][j][k][l-1]);
				}

				if((k+l)%2==0)dpk[i][j][k][l]*=a[k][l]-'0';
				
				if(dpk[i][j][k][l]>1000000000000000){
					cout<<-1<<endl;
					return 0;
				}
			}
		}
	}

	vvl dp(h,vl(w,0));
	dp[0][0]=a[0][0]-'0';

	loop(z,1,h+w-2){
		rep(zz,naname[z].size()){
			ll i = naname[z][zz].first;
			ll j = naname[z][zz].second;
			
			if(a[i][j]=='*')continue;
			//上
			if(0!=i){
				dp[i][j]=max(dp[i][j],dp[i-1][j]);
			}
			//左
			if(0!=j){
				dp[i][j]=max(dp[i][j],dp[i][j-1]);
			}

		
			if((i+j)%2==0)dp[i][j]+=a[i][j]-'0';
			else continue;
			
			rep(k,i+1)rep(l,j+1){
				if((k+l)%2==1)continue;
				if(i==k&&j==l)continue;
				dp[i][j] = max(dp[i][j],dp[k][l]-(a[k][l]-'0')+dpk[k][l][i][j]);
			}
		}
	}

	if(dp[h-1][w-1]>1000000000000000){
		cout<<-1<<endl;
		return 0;
	}

	cout<<dp[h-1][w-1]<<endl;

	// rep(i,h){
	// 	rep(j,w)cout<<dp[i][j]<<" ";
	// 	cout<<endl;
	// }


}
accuracy: 1
time_ms: 30
memory_kb: 58244
final_rank: 10

code_snippet: #include <iostream>
#include <iomanip>
#include <cassert>
#include <vector>
#include <algorithm>
#include <utility>
#include <numeric>
#include <tuple>
// #include "Src/Number/IntegerDivision.hpp"
// #include "Src/Utility/BinarySearch.hpp"
// #include "Src/Sequence/CompressedSequence.hpp"
// #include "Src/Sequence/RunLengthEncoding.hpp"
// #include "Src/Algebra/Group/AdditiveGroup.hpp"
// #include "Src/DataStructure/FenwickTree/FenwickTree.hpp"
// using namespace zawa;
// #include "atcoder/modint"
// using mint = atcoder::modint998244353;
int H, W;
std::string S[50];
const long long INF = (long long)1e15 + 100;
long long add(long long l, long long r) {
    return std::min(INF, l + r);
}
long long mult(long long l, long long r) {
    if (l > r) std::swap(l, r);
    if (l >= (INF + r - 1) / r) return INF;
    else return l * r;
}
int main() {
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);
    std::ios::sync_with_stdio(false);
    std::cin >> H >> W;
    for (int i = 0 ; i < H ; i++) std::cin >> S[i];
    std::vector dp(H, std::vector(W, std::vector(H, std::vector<long long>(W, -1LL))));
    std::vector ep(H, std::vector(W, std::vector(H, std::vector<long long>(W, -1LL)))); // only *
    auto rec_ep = [&](auto rec, int rs, int cs, int rg, int cg) -> long long {
        if (rg < rs) return 0LL;
        if (cg < cs) return 0LL;
        assert(0 <= rs and rs <= rg and rg < H);
        assert(0 <= cs and cs <= cg and cg < W);
        assert((rs + cs) % 2 == 0);
        assert((rg + cg) % 2 == 0);
        long long& res = ep[rs][cs][rg][cg];
        if (res != -1) return res;
        const int top = S[rs][cs] - '0';
        if (rs == rg and cs == cg) return res = top;
        res = 0;
        if (rs + 1 <= rg and S[rs + 1][cs] == '*') {
            res = std::max(res, mult(top, rec(rec, rs + 2, cs, rg, cg)));
        if (res == INF) return res;
            res = std::max(res, mult(top, rec(rec, rs + 1, cs + 1, rg, cg)));
        if (res == INF) return res;
        }
        if (cs + 1 <= cg and S[rs][cs + 1] == '*') {
            res = std::max(res, mult(top, rec(rec, rs, cs + 2, rg, cg)));
        if (res == INF) return res;
            res = std::max(res, mult(top, rec(rec, rs + 1, cs + 1, rg, cg)));
        if (res == INF) return res;
        }
        return res;
    };
    auto rec_dp = [&](auto rec, int rs, int cs, int rg, int cg) -> long long {
        if (rg < rs) return 0LL;
        if (cg < cs) return 0LL;
        assert(0 <= rs and rs <= rg and rg < H);
        assert(0 <= cs and cs <= cg and cg < W);
        assert((rs + cs) % 2 == 0);
        assert((rg + cg) % 2 == 0);
        long long& res = dp[rs][cs][rg][cg];
        if (res != -1) return res;
        if (rs == rg and cs == cg) return res = S[rs][cs] - '0';
        res = rec_ep(rec_ep, rs, cs, rg, cg);
        if (res == INF) return res;
        for (int r = rs ; r <= rg ; r++) {
            for (int c = cs + ((rs - r) % 2 == 0) ; c <= cg ; c += 2) {
                assert(S[r][c] == '+' or S[r][c] == '*');
                if (S[r][c] == '+') {
                    res = std::max(res, add(rec(rec, rs, cs, r, c - 1), rec(rec, r, c + 1, rg, cg)));
        if (res == INF) return res;
                    res = std::max(res, add(rec(rec, rs, cs, r - 1, c), rec(rec, r, c + 1, rg, cg)));
        if (res == INF) return res;
                    res = std::max(res, add(rec(rec, rs, cs, r, c - 1), rec(rec, r + 1, c, rg, cg)));
        if (res == INF) return res;
                    res = std::max(res, add(rec(rec, rs, cs, r - 1, c), rec(rec, r + 1, c, rg, cg)));
        if (res == INF) return res;
                }
            }
        }
        return res;
    };
    long long ans = rec_dp(rec_dp, 0, 0, H - 1, W - 1);
    std::cout << (ans > (long long)1e15 ? -1LL : ans) << '\n';
}
accuracy: 1
time_ms: 2000
memory_kb: 112128
final_rank: 16

code_snippet: #include <iostream>
#include <iomanip>
#include <cassert>
#include <vector>
#include <algorithm>
#include <utility>
#include <numeric>
#include <tuple>
// #include "Src/Number/IntegerDivision.hpp"
// #include "Src/Utility/BinarySearch.hpp"
// #include "Src/Sequence/CompressedSequence.hpp"
// #include "Src/Sequence/RunLengthEncoding.hpp"
// #include "Src/Algebra/Group/AdditiveGroup.hpp"
// #include "Src/DataStructure/FenwickTree/FenwickTree.hpp"
// using namespace zawa;
// #include "atcoder/modint"
// using mint = atcoder::modint998244353;
int H, W;
std::string S[50];
const long long INF = (long long)1e15 + 100;
long long add(long long l, long long r) {
    return std::min(INF, l + r);
}
long long mult(long long l, long long r) {
    if (l > r) std::swap(l, r);
    if (l >= (INF + r - 1) / r) return INF;
    else return l * r;
}
int main() {
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);
    std::ios::sync_with_stdio(false);
    std::cin >> H >> W;
    for (int i = 0 ; i < H ; i++) std::cin >> S[i];
    std::vector dp(H, std::vector(W, std::vector(H, std::vector<long long>(W, -1LL))));
    std::vector ep(H, std::vector(W, std::vector(H, std::vector<long long>(W, -1LL)))); // only *
    auto rec_ep = [&](auto rec, int rs, int cs, int rg, int cg) -> long long {
        if (rg < rs) return 0LL;
        if (cg < cs) return 0LL;
        assert(0 <= rs and rs <= rg and rg < H);
        assert(0 <= cs and cs <= cg and cg < W);
        assert((rs + cs) % 2 == 0);
        assert((rg + cg) % 2 == 0);
        long long& res = ep[rs][cs][rg][cg];
        if (res != -1) return res;
        const int top = S[rs][cs] - '0';
        if (rs == rg and cs == cg) return res = top;
        res = 0;
        if (rs + 1 <= rg and S[rs + 1][cs] == '*') {
            res = std::max(res, mult(top, rec(rec, rs + 2, cs, rg, cg)));
        if (res == INF) return res;
            res = std::max(res, mult(top, rec(rec, rs + 1, cs + 1, rg, cg)));
        if (res == INF) return res;
        }
        if (cs + 1 <= cg and S[rs][cs + 1] == '*') {
            res = std::max(res, mult(top, rec(rec, rs, cs + 2, rg, cg)));
        if (res == INF) return res;
            res = std::max(res, mult(top, rec(rec, rs + 1, cs + 1, rg, cg)));
        if (res == INF) return res;
        }
        return res;
    };
    auto rec_dp = [&](auto rec, int rs, int cs, int rg, int cg) -> long long {
        if (rg < rs) return 0LL;
        if (cg < cs) return 0LL;
        assert(0 <= rs and rs <= rg and rg < H);
        assert(0 <= cs and cs <= cg and cg < W);
        assert((rs + cs) % 2 == 0);
        assert((rg + cg) % 2 == 0);
        long long& res = dp[rs][cs][rg][cg];
        if (res != -1) return res;
        if (rs == rg and cs == cg) return res = S[rs][cs] - '0';
        res = rec_ep(rec_ep, rs, cs, rg, cg);
        if (res == INF) return res;
        for (int r = rs ; r <= rg ; r++) {
            for (int c = cs + ((rs - r) % 2 == 0) ; c <= cg ; c += 2) {
                assert(S[r][c] == '+' or S[r][c] == '*');
                if (S[r][c] == '+') {
                    res = std::max(res, add(rec(rec, rs, cs, r, c - 1), rec(rec, r, c + 1, rg, cg)));
        if (res == INF) return res;
                    res = std::max(res, add(rec(rec, rs, cs, r - 1, c), rec(rec, r, c + 1, rg, cg)));
        if (res == INF) return res;
                    res = std::max(res, add(rec(rec, rs, cs, r, c - 1), rec(rec, r + 1, c, rg, cg)));
        if (res == INF) return res;
                    res = std::max(res, add(rec(rec, rs, cs, r - 1, c), rec(rec, r + 1, c, rg, cg)));
        if (res == INF) return res;
                }
            }
        }
        return res;
    };
    long long ans = rec_dp(rec_dp, 0, 0, H - 1, W - 1);
    std::cout << (ans == INF ? -1LL : ans) << '\n';
}
accuracy: 0.9743589743589743
time_ms: 1990
memory_kb: 112128
final_rank: 18

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

using namespace std;

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

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

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

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

#include <unistd.h>

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

/**
 * @brief Fast IO
 */

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

int main() {
    ll MAX = 1e16;
    int N, M;
    cin >> N >> M;
    vector<string> S(N);
    rep(i,0,N) cin >> S[i];
    vector DP1(N,vector(M,vector(N,vector<ll>(M,-1))));
    rep(i,0,N) {
        rep(j,0,M) {
            if (S[i][j] == '+') continue;
            ll X;
            if (S[i][j] == '*') X = 1;
            else X = S[i][j] - '0';
            chmax(DP1[i][j][i][j], X);
            rep(k,0,i) {
                rep(l,0,j+1) {
                    chmax(DP1[k][l][i][j], min(MAX,DP1[k][l][i-1][j]*X));
                }
            }
            rep(k,0,i+1) {
                rep(l,0,j) {
                    chmax(DP1[k][l][i][j], min(MAX,DP1[k][l][i][j-1]*X));
                }
            }
        }
    }
    vector<pair<int,int>> P;
    P.push_back({-1,0});
    rep(i,0,N) {
        rep(j,0,M) {
            if (S[i][j] == '+') P.push_back({i,j});
        }
    }
    P.push_back({N,M-1});
    int L = P.size();
    vector<vector<ll>> G(L,vector<ll>(L,-1));
    rep(i,0,L) {
        rep(j,i+1,L) {
            rep(k,0,2) {
                int ix = P[i].first+dx[k], iy = P[i].second+dy[k];
                if (ix<0||N<=ix||iy<0||M<=iy) continue;
                rep(l,0,2) {
                    int jx = P[j].first-dx[l], jy = P[j].second-dy[l];
                    if (jx<0||N<=jx||jy<0||M<=jy) continue;
                    chmax(G[i][j],DP1[ix][iy][jx][jy]);
                }
            }
        }
    }
    vector<ll> DP(L,-1);
    DP[0] = 0;
    rep(i,0,L) {
        rep(j,0,i) {
            if (G[j][i] < 0) continue;
            chmax(DP[i],min(MAX,DP[j]+G[j][i]));
        }
    }
    cout << (DP[L-1] <= 1000000000000000 ? DP[L-1] : -1) << endl;
}
accuracy: 1
time_ms: 60
memory_kb: 69396
final_rank: 13

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

typedef long long ll;
typedef __int128_t lll;
typedef long double ld;
typedef pair<ll, ll> pl;
typedef tuple<ll, ll, ll> tt;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<vvl> vvvl;
typedef vector<double> vd;
typedef vector<vd> vvd;
typedef vector<vvd> vvvd;
typedef vector<bool> vb;
typedef vector<vb> vvb;
typedef vector<vvb> vvvb;
typedef vector<char> vc;
typedef vector<vc> vvc;
typedef vector<vvc> vvvc;
typedef vector<pl> vp;
typedef vector<tt> vt;
typedef vector<string> vs;

const ll INF = 1000000010;
const ll INFL = INF * INF;
const double MYPI = acos(-1);
const ld epsilon = 1e-10;

#define ovl(a, b, c, d, e, ...) e
#define pb push_back
#define eb emplace_back
#define MP make_pair
#define DEBUG(...) DEBUG_(#__VA_ARGS__, __VA_ARGS__)
#define REP1(i, n) for (int i = 0; i < (n); i++)
#define REP2(i, l, r) for (int i = (l); i < (r); i++)
#define REP3(i, l, r, d) for (int i = (l); i < (r); i += (d))
#define REP(...) ovl(__VA_ARGS__, REP3, REP2, REP1)(__VA_ARGS__)
#define RREP1(i, n) for (int i = (n)-1; i >= 0; i--)
#define RREP2(i, l, r) for (int i = (r)-1; i >= (l); i--)
#define RREP3(i, l, r, d) for (int i = (r)-1; i >= (l); i -= (d))
#define RREP(...) ovl(__VA_ARGS__, RREP3, RREP2, RREP1)(__VA_ARGS__)
#define EACH1(e, a) for (auto &e : a)
#define EACH2(x, y, a) for (auto &[x, y] : a)
#define EACH3(x, y, z, a) for (auto &[x, y, z] : a)
#define EACH(...) ovl(__VA_ARGS__, EACH3, EACH2, EACH1)(__VA_ARGS__)
#define ALL(x) begin(x), end(x)
#define RALL(x) (x).rbegin(), (x).rend()
#define sz(x) (ll) x.size()
#define LB(a, x) (lower_bound(ALL(a), x) - a.begin())
#define UB(a, x) (upper_bound(ALL(a), x) - a.begin())
#define FLG(x, i) (((x) >> (i)) & 1)
#define CNTBIT(x) __builtin_popcountll(x)
#define TOPBIT(t) (t == 0 ? -1 : 63 - __builtin_clzll(t))
#define IN(x, a, b) ((a) <= (x) && (x) < (b))
#define int ll

template <class T, class... Ts>
void OUT(const T &a, const Ts &...b) {
    cout << a;
    (cout << ... << (cout << " ", b));
    cout << endl;
}

template <class T>
void DEBUG_(string_view name, const T &a) {
    cout << name << ": " << a << endl;
}

template <class T>
void DEBUG_(string_view name, const vector<T> &a) {
    cout << name << ": ";
    REP(i, sz(a)) cout << a[i] << " ";
    cout << endl;
}

template <class T, class U>
bool chmax(T &x, const U &y) {
    return x < y ? x = y, 1 : 0;
}
template <class T, class U>
bool chmin(T &x, const U &y) {
    return x > y ? x = y, 1 : 0;
}

template <class T>
using minheap = priority_queue<T, vector<T>, greater<T>>;

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

const vl dy = {1, 0, -1, 0, 1, -1, -1, 1};
const vl dx = {0, 1, 0, -1, 1, 1, -1, -1};

template <class T = ll>
struct Edge {
    ll from, to;
    T cost;
    ll idx;
    Edge(ll f, ll t, T c = 1, ll i = -1) : from(f), to(t), cost(c), idx(i) {}
    operator int() const { return to; }
};

template <class T = ll>
struct Graph {
    vector<vector<Edge<T>>> g;
    ll es;
    explicit Graph(ll n) : g(n), es(0) {}
    size_t size() const { return sz(g); }
    void add_directed_edge(ll from, ll to, T cost = 1) {
        g[from].eb(from, to, cost, es++);
    }
    void add_edge(ll from, ll to, T cost = 1) {
        g[from].eb(from, to, cost, es);
        g[to].eb(to, from, cost, es++);
    }
    inline vector<Edge<T>> &operator[](const int &k) { return g[k]; }
    inline const vector<Edge<T>> &operator[](const int &k) const {
        return g[k];
    }
};

//-----------------------------------------------------------------------

void solve() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout << fixed << setprecision(15);

    int H, W;
    cin >> H >> W;

    vs Ss(H);
    REP(h, H) {
        string S;
        cin >> S;
        Ss[h] = S;
    }

    vector<vector<vector<pl>>> dp(H, vector<vector<pl>>(W));
    dp[0][0].eb(0, Ss[0][0] - '0');

    auto routine = [&](auto &cands, int h, int w, int dh, int dw, int dh2,
                       int dw2) {
        bool isMul = Ss[h - dh][w - dw] == '*';
        EACH(sum, prod, dp[h - dh2][w - dw2]) {
            if (isMul)
                cands.eb(sum, prod * (Ss[h][w] - '0'));
            else
                cands.eb(sum + prod, Ss[h][w] - '0');
        }
    };

    REP(h, H) {
        REP(w, W) {
            if ((h + w) % 2 == 1) continue;
            vector<pl> cands;
            if (h >= 2) {
                routine(cands, h, w, 1, 0, 2, 0);
            }
            if (h >= 1 && w >= 1) {
                routine(cands, h, w, 1, 0, 1, 1);
                routine(cands, h, w, 0, 1, 1, 1);
            }
            if (w >= 2) {
                routine(cands, h, w, 0, 1, 0, 2);
            }
            // DEBUG(cands.size());
            sort(RALL(cands));
            EACH(sum, prod, cands) {
                bool ok = dp[h][w].empty();
                EACH(seenSum, seenProd, dp[h][w]) {
                    if (sum > seenSum || prod > seenProd) {
                        ok = true;
                        break;
                    }
                }
                if (!ok) continue;
                if (sum + prod <= 1e15) {
                    dp[h][w].eb(sum, prod);
                } else {
                    cout << -1 << endl;
                    return;
                }
            }
        }
    }

    ll ans = 0;
    EACH(sum, prod, dp[H - 1][W - 1]) { chmax(ans, sum + prod); }
    cout << ans << endl;
}

signed main() {
    int T = 1;
    // cin >> T;

    while (T--) solve();

    // random_test();

    return 0;
}
accuracy: 1
time_ms: 340
memory_kb: 173168
final_rank: 15

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

typedef long long ll;
typedef __int128_t lll;
typedef long double ld;
typedef pair<ll, ll> pl;
typedef tuple<ll, ll, ll> tt;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<vvl> vvvl;
typedef vector<double> vd;
typedef vector<vd> vvd;
typedef vector<vvd> vvvd;
typedef vector<bool> vb;
typedef vector<vb> vvb;
typedef vector<vvb> vvvb;
typedef vector<char> vc;
typedef vector<vc> vvc;
typedef vector<vvc> vvvc;
typedef vector<pl> vp;
typedef vector<tt> vt;
typedef vector<string> vs;

const ll INF = 1000000010;
const ll INFL = INF * INF;
const double MYPI = acos(-1);
const ld epsilon = 1e-10;

#define ovl(a, b, c, d, e, ...) e
#define pb push_back
#define eb emplace_back
#define MP make_pair
#define DEBUG(...) DEBUG_(#__VA_ARGS__, __VA_ARGS__)
#define REP1(i, n) for (int i = 0; i < (n); i++)
#define REP2(i, l, r) for (int i = (l); i < (r); i++)
#define REP3(i, l, r, d) for (int i = (l); i < (r); i += (d))
#define REP(...) ovl(__VA_ARGS__, REP3, REP2, REP1)(__VA_ARGS__)
#define RREP1(i, n) for (int i = (n)-1; i >= 0; i--)
#define RREP2(i, l, r) for (int i = (r)-1; i >= (l); i--)
#define RREP3(i, l, r, d) for (int i = (r)-1; i >= (l); i -= (d))
#define RREP(...) ovl(__VA_ARGS__, RREP3, RREP2, RREP1)(__VA_ARGS__)
#define EACH1(e, a) for (auto &e : a)
#define EACH2(x, y, a) for (auto &[x, y] : a)
#define EACH3(x, y, z, a) for (auto &[x, y, z] : a)
#define EACH(...) ovl(__VA_ARGS__, EACH3, EACH2, EACH1)(__VA_ARGS__)
#define ALL(x) begin(x), end(x)
#define RALL(x) (x).rbegin(), (x).rend()
#define sz(x) (ll) x.size()
#define LB(a, x) (lower_bound(ALL(a), x) - a.begin())
#define UB(a, x) (upper_bound(ALL(a), x) - a.begin())
#define FLG(x, i) (((x) >> (i)) & 1)
#define CNTBIT(x) __builtin_popcountll(x)
#define TOPBIT(t) (t == 0 ? -1 : 63 - __builtin_clzll(t))
#define IN(x, a, b) ((a) <= (x) && (x) < (b))
#define int ll

template <class T, class... Ts>
void OUT(const T &a, const Ts &...b) {
    cout << a;
    (cout << ... << (cout << " ", b));
    cout << endl;
}

template <class T>
void DEBUG_(string_view name, const T &a) {
    cout << name << ": " << a << endl;
}

template <class T>
void DEBUG_(string_view name, const vector<T> &a) {
    cout << name << ": ";
    REP(i, sz(a)) cout << a[i] << " ";
    cout << endl;
}

template <class T, class U>
bool chmax(T &x, const U &y) {
    return x < y ? x = y, 1 : 0;
}
template <class T, class U>
bool chmin(T &x, const U &y) {
    return x > y ? x = y, 1 : 0;
}

template <class T>
using minheap = priority_queue<T, vector<T>, greater<T>>;

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

const vl dy = {1, 0, -1, 0, 1, -1, -1, 1};
const vl dx = {0, 1, 0, -1, 1, 1, -1, -1};

template <class T = ll>
struct Edge {
    ll from, to;
    T cost;
    ll idx;
    Edge(ll f, ll t, T c = 1, ll i = -1) : from(f), to(t), cost(c), idx(i) {}
    operator int() const { return to; }
};

template <class T = ll>
struct Graph {
    vector<vector<Edge<T>>> g;
    ll es;
    explicit Graph(ll n) : g(n), es(0) {}
    size_t size() const { return sz(g); }
    void add_directed_edge(ll from, ll to, T cost = 1) {
        g[from].eb(from, to, cost, es++);
    }
    void add_edge(ll from, ll to, T cost = 1) {
        g[from].eb(from, to, cost, es);
        g[to].eb(to, from, cost, es++);
    }
    inline vector<Edge<T>> &operator[](const int &k) { return g[k]; }
    inline const vector<Edge<T>> &operator[](const int &k) const {
        return g[k];
    }
};

//-----------------------------------------------------------------------

void solve() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout << fixed << setprecision(15);

    int H, W;
    cin >> H >> W;

    vs Ss(H);
    REP(h, H) {
        string S;
        cin >> S;
        Ss[h] = S;
    }

    vector<vector<vector<pl>>> dp(H, vector<vector<pl>>(W));
    dp[0][0].eb(0, Ss[0][0] - '0');

    auto routine = [&](auto &cands, int h, int w, int dh, int dw, int dh2,
                       int dw2) {
        bool isMul = Ss[h - dh][w - dw] == '*';
        EACH(sum, prod, dp[h - dh2][w - dw2]) {
            if (isMul)
                cands.eb(sum, prod * (Ss[h][w] - '0'));
            else
                cands.eb(sum + prod, Ss[h][w] - '0');
        }
    };

    REP(h, H) {
        REP(w, W) {
            if ((h + w) % 2 == 1) continue;
            vector<pl> cands;
            if (h >= 2) {
                routine(cands, h, w, 1, 0, 2, 0);
            }
            if (h >= 1 && w >= 1) {
                routine(cands, h, w, 1, 0, 1, 1);
                routine(cands, h, w, 0, 1, 1, 1);
            }
            if (w >= 2) {
                routine(cands, h, w, 0, 1, 0, 2);
            }
            // DEBUG(cands.size());
            sort(RALL(cands));
            EACH(sum, prod, cands) {
                bool ok = dp[h][w].empty();
                EACH(seenSum, seenProd, dp[h][w]) {
                    if (sum > seenSum || prod > seenProd) {
                        ok = true;
                        break;
                    }
                }
                if (!ok) continue;
                if (sum <= 1e15 && prod <= 1e15) {
                    dp[h][w].eb(sum, prod);
                } else {
                    cout << -1 << endl;
                    return;
                }
            }
        }
    }

    ll ans = 0;
    EACH(sum, prod, dp[H - 1][W - 1]) { chmax(ans, sum + prod); }
    cout << ans << endl;
}

signed main() {
    int T = 1;
    // cin >> T;

    while (T--) solve();

    // random_test();

    return 0;
}
accuracy: 0.9743589743589743
time_ms: 340
memory_kb: 177264
final_rank: 17

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

#define rng(i, l, r) for(int i = int(l); i < int(r); i++)
#define rep(i, n) rng(i, 0, n)
#define sz(v) int(v.size())
#define foa(s, v) for(auto &s : v)
#define all(v) v.begin(), v.end()

// clang-format off
template <class T> using V = vector<T>;
template <class T> bool chmin(T &a, T b) { return a > b ? a = b, 1 : 0; }
template <class T> bool chmax(T &a, T b) { return a < b ? a = b, 1 : 0; }
// clang-format on

constexpr ll INF = 1000000000000000LL;

#ifdef LOCAL
#define debug(x) cerr << #x << ": " << x << endl
#else
#define debug(x) void(0)
#endif

template <class T>
ostream &operator<<(ostream &os, const vector<T> &vec) {
	os << "{ ";
	foa(c, vec) os << c << ", ";
	os << "} ";
	return os;
}

int h;
ll solve() {
	int w;
	cin >> w;
	vector<string> s(h);
	foa(t, s) cin >> t;

	vector<vector<int>> gid(h, vector<int>(w));
	int idx = 0;
	foa(r, gid) foa(c, r) c = idx++;

	vector<vector<ll>> mult(idx, vector<ll>(idx, -1LL));

	rep(fx, h) rep(fy, w) {
		if(!isdigit(s[fx][fy])) continue;
		const int start = gid[fx][fy];
		auto &vec = mult[start];
		vec[start] = s[fx][fy] - '0';

		rng(i, fx, h) rng(j, fy, w) {
			const int place_id = gid[i][j];
			const char c = s[i][j];
			if(place_id == start) continue;
			ll &val = vec[place_id];
			if(isdigit(c)) {
				if(i) { chmax(val, vec[gid[i - 1][j]]); }
				if(j) { chmax(val, vec[gid[i][j - 1]]); }
				if(val < 0) continue;
				val *= int(c - '0');
				if(val > INF) return INF + 1;
			} else {
				if(c == '*') {
					if(i) { chmax(val, vec[gid[i - 1][j]]); }
					if(j) { chmax(val, vec[gid[i][j - 1]]); }
				}
			}
		}

		debug(start);
		debug(vec);
	}

	vector<ll> dp(idx, -1LL), before_add(idx, -1LL);
	before_add.front() = 0LL;

	rep(x, h) rep(y, w) {
		const int place = gid[x][y];
		ll &val = dp[place];
		ll &b = before_add[place];
		if(isdigit(s[x][y])) {
			if(x) { chmax(b, dp[gid[x - 1][y]]); }
			if(y) { chmax(b, dp[gid[x][y - 1]]); }

			rep(sx, x + 1) rep(sy, y + 1) {
				int start_id = gid[sx][sy];
				const ll preval = before_add[start_id];
				const ll add = mult[start_id][place];
				if(preval < 0 || add < 0) continue;
				chmax(val, preval + add);
			}
			if(val > INF) return INF + 1;
		} else if(s[x][y] == '+') {
			if(x) { chmax(val, dp[gid[x - 1][y]]); }
			if(y) { chmax(val, dp[gid[x][y - 1]]); }
		}
	}

	debug(before_add);
	debug(dp);

	return dp.back();
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	while(cin >> h && h) {
		ll ret = solve();
		cout << (ret > INF ? -1 : ret) << endl;
	}
}
accuracy: 1
time_ms: 20
memory_kb: 52180
final_rank: 9

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

#ifdef _RUTHEN
#include "debug.hpp"
#else
#define show(...) true
#endif

using ll = long long;
#define rep(i, n) for (int i = 0; i < (n); i++)
#define ALL(x) begin(x), end(x)
template <class T> using V = vector<T>;

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

const ll INF = 1000000000000000LL;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    ll H, W;
    cin >> H >> W;
    V<string> a(H);
    rep(i, H) cin >> a[i];
    V<V<ll>> b(H, V<ll>(W, 0));
    rep(i, H) rep(j, W) {
        if ('0' <= a[i][j] && a[i][j] <= '9') b[i][j] = a[i][j] - '0';
    }
    V<V<map<ll, ll>>> dp(H, V<map<ll, ll>>(W));
    dp[0][0][b[0][0]] = 0;
    rep(i, H) {
        for (int j = i % 2; j < W; j += 2) {
            for (auto &p : dp[i][j]) {
                if (p.first + p.second > INF) {
                    cout << -1 << '\n';
                    return 0;
                }
            }
            show(i, j, dp[i][j]);
            if (i + 2 < H) {
                if (a[i + 1][j] == '*') {
                    for (auto &p : dp[i][j]) chmax(dp[i + 2][j][p.first * b[i + 2][j]], p.second);
                } else {
                    for (auto &p : dp[i][j]) chmax(dp[i + 2][j][b[i + 2][j]], p.first + p.second);
                }
            }
            if (j + 2 < W) {
                if (a[i][j + 1] == '*') {
                    for (auto &p : dp[i][j]) chmax(dp[i][j + 2][p.first * b[i][j + 2]], p.second);
                } else {
                    for (auto &p : dp[i][j]) chmax(dp[i][j + 2][b[i][j + 2]], p.first + p.second);
                }
            }
            if (i + 1 < H && j + 1 < W) {
                if (a[i][j + 1] == '*' || a[i + 1][j] == '*') {
                    for (auto &p : dp[i][j]) chmax(dp[i + 1][j + 1][p.first * b[i + 1][j + 1]], p.second);
                }
                if (a[i][j + 1] == '+' || a[i + 1][j] == '+') {
                    for (auto &p : dp[i][j]) chmax(dp[i + 1][j + 1][b[i + 1][j + 1]], p.first + p.second);
                }
            }
        }
    }
    ll ans = 0;
    for (auto &p : dp[H - 1][W - 1]) chmax(ans, p.first + p.second);
    cout << (ans > INF ? -1 : ans) << '\n';
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 10904
final_rank: 2

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

#ifdef _RUTHEN
#include "debug.hpp"
#else
#define show(...) true
#endif

using ll = long long;
#define rep(i, n) for (int i = 0; i < (n); i++)
#define ALL(x) begin(x), end(x)
template <class T> using V = vector<T>;

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

const ll INF = 1000000000000000LL;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    ll H, W;
    cin >> H >> W;
    V<string> a(H);
    rep(i, H) cin >> a[i];
    V<V<ll>> b(H, V<ll>(W, 0));
    rep(i, H) rep(j, W) {
        if ('0' <= a[i][j] && a[i][j] <= '9') b[i][j] = a[i][j] - '0';
    }
    V<V<map<ll, ll>>> dp(H, V<map<ll, ll>>(W));
    dp[0][0][b[0][0]] = 0;
    rep(i, H) {
        for (int j = i % 2; j < W; j += 2) {
            for (auto &p : dp[i][j]) {
                if (p.first + p.second > INF) {
                    cout << -1 << '\n';
                    return 0;
                }
            }
            show(i, j, dp[i][j]);
            if (i + 2 < H) {
                if (a[i + 1][j] == '*') {
                    for (auto &p : dp[i][j]) chmax(dp[i + 2][j][p.first * b[i + 2][j]], p.second);
                } else {
                    for (auto &p : dp[i][j]) chmax(dp[i + 2][j][b[i + 2][j]], p.first + p.second);
                }
            }
            if (j + 2 < W) {
                if (a[i][j + 1] == '*') {
                    for (auto &p : dp[i][j]) chmax(dp[i][j + 2][p.first * b[i][j + 2]], p.second);
                } else {
                    for (auto &p : dp[i][j]) chmax(dp[i][j + 2][b[i][j + 2]], p.first + p.second);
                }
            }
            if (i + 1 < H && j + 1 < W) {
                if (a[i][j + 1] == '*' || a[i + 1][j] == '*') {
                    for (auto &p : dp[i][j]) chmax(dp[i + 1][j + 1][p.first * b[i + 1][j + 1]], p.second);
                }
                if (a[i][j + 1] == '+' || a[i + 1][j] == '+') {
                    for (auto &p : dp[i][j]) chmax(dp[i + 1][j + 1][b[i + 1][j + 1]], p.first + p.second);
                }
            }
        }
    }
    ll ans = 0;
    for (auto &p : dp[H - 1][W - 1]) chmax(ans, p.first + p.second);
    cout << (ans > INF ? -1 : ans) << '\n';
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 10928
final_rank: 3

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

typedef string::const_iterator State;
#define eps 1e-8L
#define MAX_MOD 1000000007LL
#define GYAKU 500000004LL
#define MOD 998244353LL
#define pb push_back
#define mp make_pair
typedef long long ll;
typedef long double ld;
#define REP(a, b) for (long long(a) = 0; (a) < (b); ++(a))
#define ALL(x) (x).begin(), (x).end()

#define int long long
int dp[53][53][53][53];
int dp2[53][53];
void solve()
{
  int h, w;
  cin >> h >> w;
  vector<string> inputs;
  REP(i, h)
  {
    string s;
    cin >> s;
    inputs.push_back(s);
  }
  REP(i, h)
  {
    REP(q, w)
    {
      if ((i + q) % 2 == 1)
        continue;
      dp[i][q][i][q] = inputs[i][q] - '0';
      for (int j = i; j < h; ++j)
      {
        for (int t = q; t < w; ++t)
        {
          if ((j + t) % 2 == 1)
            continue;
          if (j + 1 < h)
          {
            if (inputs[j + 1][t] == '*')
            {
              if (j + 2 < h)
              {
                dp[i][q][j + 2][t] = max(dp[i][q][j + 2][t], dp[i][q][j][t] * (int)(inputs[j + 2][t] - '0'));
                dp[i][q][j + 2][t] = min(dp[i][q][j + 2][t], (int)1e16);
              }
              if (t + 1 < w)
              {
                dp[i][q][j + 1][t + 1] = max(dp[i][q][j + 1][t + 1], dp[i][q][j][t] * (int)(inputs[j + 1][t + 1] - '0'));
                dp[i][q][j + 1][t + 1] = min(dp[i][q][j + 1][t + 1], (int)1e16);
              }
            }
          }
          if (t + 1 < w)
          {
            if (inputs[j][t + 1] == '*')
            {
              if (t + 2 < w)
              {
                dp[i][q][j][t + 2] = max(dp[i][q][j][t + 2], dp[i][q][j][t] * (int)(inputs[j][t + 2] - '0'));
                dp[i][q][j][t + 2] = min(dp[i][q][j][t + 2], (int)1e16);
              }
              if (j + 1 < h)
              {
                dp[i][q][j + 1][t + 1] = max(dp[i][q][j + 1][t + 1], dp[i][q][j][t] * (int)(inputs[j + 1][t + 1] - '0'));
                dp[i][q][j + 1][t + 1] = min(dp[i][q][j + 1][t + 1], (int)1e16);
              }
            }
          }
        }
      }
    }
  }

  int ans = 0;
  REP(i, h)
  {
    REP(q, w)
    {
      REP(j, h)
      {
        REP(t, w)
        {
          if (dp[i][q][j][t] == 0)
            continue;
          if (j == h - 1 and t == w - 1)
          {
            ans = max(ans, dp2[i][q] + dp[i][q][j][t]);
          }
          else
          {
            if (j + 1 < h)
            {
              if (inputs[j + 1][t] == '+')
              {
                dp2[j + 2][t] = max(dp2[j + 2][t], dp2[i][q] + dp[i][q][j][t]);
                if (t + 1 < w)
                {
                  dp2[j + 1][t + 1] = max(dp2[j + 1][t + 1], dp2[i][q] + dp[i][q][j][t]);
                }
              }
            }
            if (t + 1 < w)
            {
              if (inputs[j][t + 1] == '+')
              {
                dp2[j][t + 2] = max(dp2[j][t + 2], dp2[i][q] + dp[i][q][j][t]);
                if (j + 1 < h)
                {
                  dp2[j + 1][t + 1] = max(dp2[j + 1][t + 1], dp2[i][q] + dp[i][q][j][t]);
                }
              }
            }
          }
        }
      }
    }
  }
  if (ans > 1e15)
  {
    ans = -1;
  }
  cout << ans << endl;
}
#undef int

// generated by oj-template v4.7.2
// (https://github.com/online-judge-tools/template-generator)
int main()
{
  // Fasterize input/output script
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  cout << fixed << setprecision(100);
  // scanf/printf user should delete this fasterize input/output script

  int t = 1;
  // cin >> t; // comment out if solving multi testcase
  for (int testCase = 1; testCase <= t; ++testCase)
  {
    solve();
  }
  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 61888
final_rank: 11

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

const long long INF = 1e15;

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    int H, W;
    cin >> H >> W;
    vector<string> S(H);
    for (auto& s : S) cin >> s;

    vector<vector<map<ll, ll>>> dp(H, vector<map<ll, ll>>(W));
    dp[0][0][1] = 0;
    ll ans = 0;

    for (int i = 0; i < H; i++) {
        for (int j = 0; j < W; j++) {
            for (auto p : dp[i][j]) {
                ll k = p.first, val = p.second;
                if (!((i + j) & 1)) {
                    k *= S[i][j] - '0';
                    if (k > INF) {
                        cout << -1 << '\n';
                        return 0;
                    }
                    ans = max(ans, val + k);
                } else if (S[i][j] == '+') {
                    val += k;
                    if (val > INF) {
                        cout << -1 << '\n';
                        return 0;
                    }
                    k = 1;
                }
                for (int l = 0; l < 2; l++) {
                    int nx = i + l, ny = j + (l ^ 1);
                    if (H <= nx || W <= ny) continue;
                    if (!dp[nx][ny].count(k))
                        dp[nx][ny][k] = val;
                    else
                        dp[nx][ny][k] = max(dp[nx][ny][k], val);
                }
            }
        }
    }

    cout << (ans > INF ? -1 : ans) << '\n';
    return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 18648
final_rank: 4

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

const long long INF = 1e15;

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    int H, W;
    cin >> H >> W;
    vector<string> S(H);
    for (auto& s : S) cin >> s;

    vector<int> prime = {2, 3, 5, 7};
    vector<vector<ll>> power(4, {1});
    for (int i = 0; i < 4; i++) {
        while (power[i].back() * prime[i] <= INF) {
            power[i].emplace_back(power[i].back() * prime[i]);
        }
    }
    vector<ll> prod;
    for (auto& x : power[0]) {
        for (auto& y : power[1]) {
            for (auto& z : power[2]) {
                for (auto& w : power[3]) {
                    ll cur = 1;
                    cur *= x;
                    if (2 * INF / cur < y) continue;
                    cur *= y;
                    if (2 * INF / cur < z) continue;
                    cur *= z;
                    if (2 * INF / cur < w) continue;
                    cur *= w;
                    if (cur <= INF) prod.emplace_back(cur);
                }
            }
        }
    }
    sort(prod.begin(), prod.end());
    vector<vector<map<ll, ll>>> dp(H, vector<map<ll, ll>>(W));
    dp[0][0][1] = 0;
    ll ans = 0;

    for (int i = 0; i < H; i++) {
        for (int j = 0; j < W; j++) {
            for (auto k : prod) {
                if (!dp[i][j].count(k)) continue;
                ll val = dp[i][j][k];
                if (!((i + j) & 1)) {
                    k *= S[i][j] - '0';
                    if (k > INF) {
                        cout << -1 << '\n';
                        return 0;
                    }
                    ans = max(ans, val + k);
                } else if (S[i][j] == '+') {
                    val += k;
                    if (val > INF) {
                        cout << -1 << '\n';
                        return 0;
                    }
                    k = 1;
                }
                for (int l = 0; l < 2; l++) {
                    int nx = i + l, ny = j + (l ^ 1);
                    if (H <= nx || W <= ny) continue;
                    if (!dp[nx][ny].count(k))
                        dp[nx][ny][k] = val;
                    else
                        dp[nx][ny][k] = max(dp[nx][ny][k], val);
                }
            }
        }
    }

    cout << (ans > INF ? -1 : ans) << '\n';
    return 0;
}
accuracy: 1
time_ms: 240
memory_kb: 18764
final_rank: 6

code_snippet: #define LOCAL
#include <bits/stdc++.h>
using namespace std;
#pragma region Macros
typedef long long ll;
typedef __int128_t i128;
typedef unsigned int uint;
typedef unsigned long long ull;
#define ALL(x) (x).begin(), (x).end()

template <typename T> istream& operator>>(istream& is, vector<T>& v) {
    for (T& x : v) is >> x;
    return is;
}
template <typename T> ostream& operator<<(ostream& os, const vector<T>& v) {
    for (int i = 0; i < (int)v.size(); i++) {
        os << v[i] << (i + 1 == (int)v.size() ? "" : " ");
    }
    return os;
}
template <typename T, typename U> ostream& operator<<(ostream& os, const pair<T, U>& p) {
    os << '(' << p.first << ',' << p.second << ')';
    return os;
}
template <typename T, typename U> ostream& operator<<(ostream& os, const map<T, U>& m) {
    os << '{';
    for (auto itr = m.begin(); itr != m.end();) {
        os << '(' << itr->first << ',' << itr->second << ')';
        if (++itr != m.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T, typename U> ostream& operator<<(ostream& os, const unordered_map<T, U>& m) {
    os << '{';
    for (auto itr = m.begin(); itr != m.end();) {
        os << '(' << itr->first << ',' << itr->second << ')';
        if (++itr != m.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T> ostream& operator<<(ostream& os, const set<T>& s) {
    os << '{';
    for (auto itr = s.begin(); itr != s.end();) {
        os << *itr;
        if (++itr != s.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T> ostream& operator<<(ostream& os, const multiset<T>& s) {
    os << '{';
    for (auto itr = s.begin(); itr != s.end();) {
        os << *itr;
        if (++itr != s.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T> ostream& operator<<(ostream& os, const unordered_set<T>& s) {
    os << '{';
    for (auto itr = s.begin(); itr != s.end();) {
        os << *itr;
        if (++itr != s.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T> ostream& operator<<(ostream& os, const deque<T>& v) {
    for (int i = 0; i < (int)v.size(); i++) {
        os << v[i] << (i + 1 == (int)v.size() ? "" : " ");
    }
    return os;
}

template <int i, typename T> void print_tuple(ostream&, const T&) {}
template <int i, typename T, typename H, class... Args> void print_tuple(ostream& os, const T& t) {
    if (i) os << ',';
    os << get<i>(t);
    print_tuple<i + 1, T, Args...>(os, t);
}
template <typename... Args> ostream& operator<<(ostream& os, const tuple<Args...>& t) {
    os << '{';
    print_tuple<0, tuple<Args...>, Args...>(os, t);
    return os << '}';
}

void debug_out() { cerr << '\n'; }
template <class Head, class... Tail> void debug_out(Head&& head, Tail&&... tail) {
    cerr << head;
    if (sizeof...(Tail) > 0) cerr << ", ";
    debug_out(move(tail)...);
}
#ifdef LOCAL
#define debug(...)                                                                   \
    cerr << " ";                                                                     \
    cerr << #__VA_ARGS__ << " :[" << __LINE__ << ":" << __FUNCTION__ << "]" << '\n'; \
    cerr << " ";                                                                     \
    debug_out(__VA_ARGS__)
#else
#define debug(...) 42
#endif

template <typename T> T gcd(T x, T y) { return y != 0 ? gcd(y, x % y) : x; }
template <typename T> T lcm(T x, T y) { return x / gcd(x, y) * y; }

int topbit(signed t) { return t == 0 ? -1 : 31 - __builtin_clz(t); }
int topbit(long long t) { return t == 0 ? -1 : 63 - __builtin_clzll(t); }
int botbit(signed a) { return a == 0 ? 32 : __builtin_ctz(a); }
int botbit(long long a) { return a == 0 ? 64 : __builtin_ctzll(a); }
int popcount(signed t) { return __builtin_popcount(t); }
int popcount(long long t) { return __builtin_popcountll(t); }
bool ispow2(int i) { return i && (i & -i) == i; }

template <class T> T ceil(T x, T y) {
    assert(y >= 1);
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <class T> T floor(T x, T y) {
    assert(y >= 1);
    return (x > 0 ? x / y : (x - y + 1) / y);
}

template <class T1, class T2> inline bool chmin(T1& a, T2 b) {
    if (a > b) {
        a = b;
        return true;
    }
    return false;
}
template <class T1, class T2> inline bool chmax(T1& a, T2 b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}
#pragma endregion

const long long INF = 1e15;
const int dx[4] = {1, 0, -1, 0}, dy[4] = {0, 1, 0, -1};
const char dir[4] = {'D', 'R', 'U', 'L'};
const long long MOD = 1000000007;
// const long long MOD = 998244353;

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    int H, W;
    cin >> H >> W;
    vector<string> S(H);
    for (auto& s : S) cin >> s;

    vector<int> prime = {2, 3, 5, 7};
    vector<vector<ll>> power(4, {1});
    for (int i = 0; i < 4; i++) {
        while (power[i].back() * prime[i] <= INF) {
            power[i].emplace_back(power[i].back() * prime[i]);
        }
    }
    vector<ll> prod;
    for (auto& x : power[0]) {
        for (auto& y : power[1]) {
            for (auto& z : power[2]) {
                for (auto& w : power[3]) {
                    ll cur = 1;
                    cur *= x;
                    if (2 * INF / cur < y) continue;
                    cur *= y;
                    if (2 * INF / cur < z) continue;
                    cur *= z;
                    if (2 * INF / cur < w) continue;
                    cur *= w;
                    if (cur <= INF) prod.emplace_back(cur);
                }
            }
        }
    }
    sort(prod.begin(), prod.end());
    vector<vector<map<ll, ll>>> dp(H, vector<map<ll, ll>>(W));
    dp[0][0][1] = 0;
    ll ans = 0;

    for (int i = 0; i < H; i++) {
        for (int j = 0; j < W; j++) {
            for (auto k : prod) {
                if (!dp[i][j].count(k)) continue;
                ll val = dp[i][j][k];
                if (!((i + j) & 1)) {
                    k *= S[i][j] - '0';
                    if (k > INF) {
                        cout << -1 << '\n';
                        return 0;
                    }
                    ans = max(ans, val + k);
                } else if (S[i][j] == '+') {
                    val += k;
                    if (val > INF) {
                        cout << -1 << '\n';
                        return 0;
                    }
                    k = 1;
                }
                for (int l = 0; l < 2; l++) {
                    int nx = i + l, ny = j + (l ^ 1);
                    if (H <= nx || W <= ny) continue;
                    if (!dp[nx][ny].count(k))
                        dp[nx][ny][k] = val;
                    else
                        dp[nx][ny][k] = max(dp[nx][ny][k], val);
                }
            }
        }
    }

    cout << (ans > INF ? -1 : ans) << '\n';
    return 0;
}
accuracy: 1
time_ms: 240
memory_kb: 18788
final_rank: 7

code_snippet: #define LOCAL
#include <bits/stdc++.h>
using namespace std;
#pragma region Macros
typedef long long ll;
typedef __int128_t i128;
typedef unsigned int uint;
typedef unsigned long long ull;
#define ALL(x) (x).begin(), (x).end()

template <typename T> istream& operator>>(istream& is, vector<T>& v) {
    for (T& x : v) is >> x;
    return is;
}
template <typename T> ostream& operator<<(ostream& os, const vector<T>& v) {
    for (int i = 0; i < (int)v.size(); i++) {
        os << v[i] << (i + 1 == (int)v.size() ? "" : " ");
    }
    return os;
}
template <typename T, typename U> ostream& operator<<(ostream& os, const pair<T, U>& p) {
    os << '(' << p.first << ',' << p.second << ')';
    return os;
}
template <typename T, typename U> ostream& operator<<(ostream& os, const map<T, U>& m) {
    os << '{';
    for (auto itr = m.begin(); itr != m.end();) {
        os << '(' << itr->first << ',' << itr->second << ')';
        if (++itr != m.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T, typename U> ostream& operator<<(ostream& os, const unordered_map<T, U>& m) {
    os << '{';
    for (auto itr = m.begin(); itr != m.end();) {
        os << '(' << itr->first << ',' << itr->second << ')';
        if (++itr != m.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T> ostream& operator<<(ostream& os, const set<T>& s) {
    os << '{';
    for (auto itr = s.begin(); itr != s.end();) {
        os << *itr;
        if (++itr != s.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T> ostream& operator<<(ostream& os, const multiset<T>& s) {
    os << '{';
    for (auto itr = s.begin(); itr != s.end();) {
        os << *itr;
        if (++itr != s.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T> ostream& operator<<(ostream& os, const unordered_set<T>& s) {
    os << '{';
    for (auto itr = s.begin(); itr != s.end();) {
        os << *itr;
        if (++itr != s.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T> ostream& operator<<(ostream& os, const deque<T>& v) {
    for (int i = 0; i < (int)v.size(); i++) {
        os << v[i] << (i + 1 == (int)v.size() ? "" : " ");
    }
    return os;
}

template <int i, typename T> void print_tuple(ostream&, const T&) {}
template <int i, typename T, typename H, class... Args> void print_tuple(ostream& os, const T& t) {
    if (i) os << ',';
    os << get<i>(t);
    print_tuple<i + 1, T, Args...>(os, t);
}
template <typename... Args> ostream& operator<<(ostream& os, const tuple<Args...>& t) {
    os << '{';
    print_tuple<0, tuple<Args...>, Args...>(os, t);
    return os << '}';
}

void debug_out() { cerr << '\n'; }
template <class Head, class... Tail> void debug_out(Head&& head, Tail&&... tail) {
    cerr << head;
    if (sizeof...(Tail) > 0) cerr << ", ";
    debug_out(move(tail)...);
}
#ifdef LOCAL
#define debug(...)                                                                   \
    cerr << " ";                                                                     \
    cerr << #__VA_ARGS__ << " :[" << __LINE__ << ":" << __FUNCTION__ << "]" << '\n'; \
    cerr << " ";                                                                     \
    debug_out(__VA_ARGS__)
#else
#define debug(...) 42
#endif

template <typename T> T gcd(T x, T y) { return y != 0 ? gcd(y, x % y) : x; }
template <typename T> T lcm(T x, T y) { return x / gcd(x, y) * y; }

int topbit(signed t) { return t == 0 ? -1 : 31 - __builtin_clz(t); }
int topbit(long long t) { return t == 0 ? -1 : 63 - __builtin_clzll(t); }
int botbit(signed a) { return a == 0 ? 32 : __builtin_ctz(a); }
int botbit(long long a) { return a == 0 ? 64 : __builtin_ctzll(a); }
int popcount(signed t) { return __builtin_popcount(t); }
int popcount(long long t) { return __builtin_popcountll(t); }
bool ispow2(int i) { return i && (i & -i) == i; }

template <class T> T ceil(T x, T y) {
    assert(y >= 1);
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <class T> T floor(T x, T y) {
    assert(y >= 1);
    return (x > 0 ? x / y : (x - y + 1) / y);
}

template <class T1, class T2> inline bool chmin(T1& a, T2 b) {
    if (a > b) {
        a = b;
        return true;
    }
    return false;
}
template <class T1, class T2> inline bool chmax(T1& a, T2 b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}
#pragma endregion

/**
 * @brief compress
 */
template <typename T> map<T, int> compress(vector<T>& v) {
    sort(v.begin(), v.end());
    v.erase(unique(v.begin(), v.end()), v.end());
    map<T, int> res;
    for (int i = 0; i < (int)v.size(); i++) res[v[i]] = i;
    return res;
}

const long long INF = 1e15;
const int dx[4] = {1, 0, -1, 0}, dy[4] = {0, 1, 0, -1};
const char dir[4] = {'D', 'R', 'U', 'L'};
const long long MOD = 1000000007;
// const long long MOD = 998244353;

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    int H, W;
    cin >> H >> W;
    vector<string> S(H);
    for (auto& s : S) cin >> s;

    vector<int> prime = {2, 3, 5, 7};
    vector<vector<ll>> power(4, {1});
    for (int i = 0; i < 4; i++) {
        while (power[i].back() * prime[i] <= INF) {
            power[i].emplace_back(power[i].back() * prime[i]);
        }
    }
    vector<ll> prod;
    for (auto& x : power[0]) {
        for (auto& y : power[1]) {
            for (auto& z : power[2]) {
                for (auto& w : power[3]) {
                    ll cur = 1;
                    cur *= x;
                    if (2 * INF / cur < y) continue;
                    cur *= y;
                    if (2 * INF / cur < z) continue;
                    cur *= z;
                    if (2 * INF / cur < w) continue;
                    cur *= w;
                    if (cur <= INF) prod.emplace_back(cur);
                }
            }
        }
    }
    map<ll, int> mp = compress(prod);
    int sz = mp.size();

    vector<vector<unordered_map<ll, ll>>> dp(H, vector<unordered_map<ll, ll>>(W));

    // for (int i = 0; i < H; i++) {
    //     for (int j = 0; j < W; j++) {
    //         for (int k = 0; k < sz; k++) {
    //             dp[i][j][k] = -INF * 1000;
    //         }
    //     }
    // }
    dp[0][0][0] = 0;
    ll ans = 0;

    for (int i = 0; i < H; i++) {
        for (int j = 0; j < W; j++) {
            for (int k = 0; k < sz; k++) {
                if (!dp[i][j].count(k)) continue;
                ll val = dp[i][j][k];
                // if (val < 0) continue;
                int nk = k;
                if (!((i + j) & 1)) {
                    ll nxt = prod[k] * (S[i][j] - '0');
                    if (nxt > INF) {
                        cout << -1 << '\n';
                        return 0;
                    }
                    ans = max(ans, val + nxt);
                    assert(mp.count(nxt));
                    nk = mp[nxt];
                } else if (S[i][j] == '+') {
                    val += prod[k];
                    if (val > INF) {
                        cout << -1 << '\n';
                        return 0;
                    }
                    nk = 0;
                }
                for (int l = 0; l < 2; l++) {
                    int nx = i + l, ny = j + (l ^ 1);
                    if (H <= nx || W <= ny) continue;
                    if (!dp[nx][ny].count(nk))
                        dp[nx][ny][nk] = val;
                    else
                        dp[nx][ny][nk] = max(dp[nx][ny][nk], val);
                }
            }
        }
    }

    cout << (ans > INF ? -1 : ans) << '\n';
    return 0;
}
accuracy: 1
time_ms: 720
memory_kb: 15864
final_rank: 14

code_snippet: #define LOCAL
#include <bits/stdc++.h>
using namespace std;
#pragma region Macros
typedef long long ll;
typedef __int128_t i128;
typedef unsigned int uint;
typedef unsigned long long ull;
#define ALL(x) (x).begin(), (x).end()

template <typename T> istream& operator>>(istream& is, vector<T>& v) {
    for (T& x : v) is >> x;
    return is;
}
template <typename T> ostream& operator<<(ostream& os, const vector<T>& v) {
    for (int i = 0; i < (int)v.size(); i++) {
        os << v[i] << (i + 1 == (int)v.size() ? "" : " ");
    }
    return os;
}
template <typename T, typename U> ostream& operator<<(ostream& os, const pair<T, U>& p) {
    os << '(' << p.first << ',' << p.second << ')';
    return os;
}
template <typename T, typename U> ostream& operator<<(ostream& os, const map<T, U>& m) {
    os << '{';
    for (auto itr = m.begin(); itr != m.end();) {
        os << '(' << itr->first << ',' << itr->second << ')';
        if (++itr != m.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T, typename U> ostream& operator<<(ostream& os, const unordered_map<T, U>& m) {
    os << '{';
    for (auto itr = m.begin(); itr != m.end();) {
        os << '(' << itr->first << ',' << itr->second << ')';
        if (++itr != m.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T> ostream& operator<<(ostream& os, const set<T>& s) {
    os << '{';
    for (auto itr = s.begin(); itr != s.end();) {
        os << *itr;
        if (++itr != s.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T> ostream& operator<<(ostream& os, const multiset<T>& s) {
    os << '{';
    for (auto itr = s.begin(); itr != s.end();) {
        os << *itr;
        if (++itr != s.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T> ostream& operator<<(ostream& os, const unordered_set<T>& s) {
    os << '{';
    for (auto itr = s.begin(); itr != s.end();) {
        os << *itr;
        if (++itr != s.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T> ostream& operator<<(ostream& os, const deque<T>& v) {
    for (int i = 0; i < (int)v.size(); i++) {
        os << v[i] << (i + 1 == (int)v.size() ? "" : " ");
    }
    return os;
}

template <int i, typename T> void print_tuple(ostream&, const T&) {}
template <int i, typename T, typename H, class... Args> void print_tuple(ostream& os, const T& t) {
    if (i) os << ',';
    os << get<i>(t);
    print_tuple<i + 1, T, Args...>(os, t);
}
template <typename... Args> ostream& operator<<(ostream& os, const tuple<Args...>& t) {
    os << '{';
    print_tuple<0, tuple<Args...>, Args...>(os, t);
    return os << '}';
}

void debug_out() { cerr << '\n'; }
template <class Head, class... Tail> void debug_out(Head&& head, Tail&&... tail) {
    cerr << head;
    if (sizeof...(Tail) > 0) cerr << ", ";
    debug_out(move(tail)...);
}
#ifdef LOCAL
#define debug(...)                                                                   \
    cerr << " ";                                                                     \
    cerr << #__VA_ARGS__ << " :[" << __LINE__ << ":" << __FUNCTION__ << "]" << '\n'; \
    cerr << " ";                                                                     \
    debug_out(__VA_ARGS__)
#else
#define debug(...) 42
#endif

template <typename T> T gcd(T x, T y) { return y != 0 ? gcd(y, x % y) : x; }
template <typename T> T lcm(T x, T y) { return x / gcd(x, y) * y; }

int topbit(signed t) { return t == 0 ? -1 : 31 - __builtin_clz(t); }
int topbit(long long t) { return t == 0 ? -1 : 63 - __builtin_clzll(t); }
int botbit(signed a) { return a == 0 ? 32 : __builtin_ctz(a); }
int botbit(long long a) { return a == 0 ? 64 : __builtin_ctzll(a); }
int popcount(signed t) { return __builtin_popcount(t); }
int popcount(long long t) { return __builtin_popcountll(t); }
bool ispow2(int i) { return i && (i & -i) == i; }

template <class T> T ceil(T x, T y) {
    assert(y >= 1);
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <class T> T floor(T x, T y) {
    assert(y >= 1);
    return (x > 0 ? x / y : (x - y + 1) / y);
}

template <class T1, class T2> inline bool chmin(T1& a, T2 b) {
    if (a > b) {
        a = b;
        return true;
    }
    return false;
}
template <class T1, class T2> inline bool chmax(T1& a, T2 b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}
#pragma endregion

/**
 * @brief compress
 */
template <typename T> map<T, int> compress(vector<T>& v) {
    sort(v.begin(), v.end());
    v.erase(unique(v.begin(), v.end()), v.end());
    map<T, int> res;
    for (int i = 0; i < (int)v.size(); i++) res[v[i]] = i;
    return res;
}

const long long INF = 1e15;
const int dx[4] = {1, 0, -1, 0}, dy[4] = {0, 1, 0, -1};
const char dir[4] = {'D', 'R', 'U', 'L'};
const long long MOD = 1000000007;
// const long long MOD = 998244353;

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    int H, W;
    cin >> H >> W;
    vector<string> S(H);
    for (auto& s : S) cin >> s;

    vector<int> prime = {2, 3, 5, 7};
    vector<vector<ll>> power(4, {1});
    for (int i = 0; i < 4; i++) {
        while (power[i].back() * prime[i] <= INF) {
            power[i].emplace_back(power[i].back() * prime[i]);
        }
    }
    vector<ll> prod;
    for (auto& x : power[0]) {
        for (auto& y : power[1]) {
            for (auto& z : power[2]) {
                for (auto& w : power[3]) {
                    ll cur = 1;
                    cur *= x;
                    if (2 * INF / cur < y) continue;
                    cur *= y;
                    if (2 * INF / cur < z) continue;
                    cur *= z;
                    if (2 * INF / cur < w) continue;
                    cur *= w;
                    if (cur <= INF) prod.emplace_back(cur);
                }
            }
        }
    }
    map<ll, int> mp = compress(prod);
    int sz = mp.size();

    vector<vector<map<ll, ll>>> dp(H, vector<map<ll, ll>>(W));

    // for (int i = 0; i < H; i++) {
    //     for (int j = 0; j < W; j++) {
    //         for (int k = 0; k < sz; k++) {
    //             dp[i][j][k] = -INF * 1000;
    //         }
    //     }
    // }
    dp[0][0][0] = 0;
    ll ans = 0;

    for (int i = 0; i < H; i++) {
        for (int j = 0; j < W; j++) {
            for (int k = 0; k < sz; k++) {
                if (!dp[i][j].count(k)) continue;
                ll val = dp[i][j][k];
                // if (val < 0) continue;
                int nk = k;
                if (!((i + j) & 1)) {
                    ll nxt = prod[k] * (S[i][j] - '0');
                    if (nxt > INF) {
                        cout << -1 << '\n';
                        return 0;
                    }
                    ans = max(ans, val + nxt);
                    assert(mp.count(nxt));
                    nk = mp[nxt];
                } else if (S[i][j] == '+') {
                    val += prod[k];
                    if (val > INF) {
                        cout << -1 << '\n';
                        return 0;
                    }
                    nk = 0;
                }
                for (int l = 0; l < 2; l++) {
                    int nx = i + l, ny = j + (l ^ 1);
                    if (H <= nx || W <= ny) continue;
                    if (!dp[nx][ny].count(nk))
                        dp[nx][ny][nk] = val;
                    else
                        dp[nx][ny][nk] = max(dp[nx][ny][nk], val);
                }
            }
        }
    }

    cout << (ans > INF ? -1 : ans) << '\n';
    return 0;
}
accuracy: 1
time_ms: 250
memory_kb: 21060
final_rank: 8

code_snippet: #pragma GCC target("avx2")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
using namespace std;
#define DEBUG
#ifdef DEBUG
template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << '(' << p.first << ',' << p.second << ')';
    return os;
}
template <class T> ostream &operator<<(ostream &os, const vector<T> &v) {
    os << '{';
    for(int i = 0; i < (int)v.size(); i++) {
        if(i) { os << ','; }
        os << v[i];
    }
    os << '}';
    return os;
}
void debugg() { cerr << endl; }
template <class T, class... Args>
void debugg(const T &x, const Args &... args) {
    cerr << " " << x;
    debugg(args...);
}
#define debug(...)                                                             \
    cerr << __LINE__ << " [" << #__VA_ARGS__ << "]: ", debugg(__VA_ARGS__)
#define dump(x) cerr << __LINE__ << " " << #x << " = " << (x) << endl
#else
#define debug(...) (void(0))
#define dump(x) (void(0))
#endif
using namespace std;
typedef long long ll;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<char> vc;
typedef vector<string> vs;
typedef vector<bool> vb;
typedef vector<double> vd;
typedef pair<ll,ll> P;
typedef pair<int,int> pii;
typedef vector<P> vpl;
typedef tuple<ll,ll,ll> tapu;
#define rep(i,n) for(int i=0; i<(n); i++)
#define REP(i,a,b) for(int i=(a); i<(b); i++)
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
const int inf = (1<<30)-1;
const ll linf = 1LL<<61;
const int MAX = 510000;
int dy[8] = {0,1,0,-1,1,-1,-1,1};
int dx[8] = {-1,0,1,0,1,-1,1,-1};
const double pi = acos(-1);
const double eps = 1e-7;
template<typename T1,typename T2> inline bool chmin(T1 &a,T2 b){
	if(a>b){
		a = b; return true;
	}
	else return false;
}
template<typename T1,typename T2> inline bool chmax(T1 &a,T2 b){
	if(a<b){
		a = b; return true;
	}
	else return false;
}
template<typename T> inline void print(T &a){
    int sz = a.size();
    for(auto itr = a.begin(); itr != a.end(); itr++){
		cout << *itr;
        sz--;
        if(sz) cout << " ";
	}
    cout << "\n";
}
template<typename T1,typename T2> inline void print2(T1 a, T2 b){
	cout << a << " " << b << "\n";
}
template<typename T1,typename T2,typename T3> inline void print3(T1 a, T2 b, T3 c){
	cout << a << " " << b << " " << c << "\n";
}
void mark() {cout << "#" << "\n";}
ll pcount(ll x) {return __builtin_popcountll(x);}
//const int mod = 1e9 + 7;
const int mod = 998244353;
//#include <atcoder/all>
//using namespace atcoder;

ll mul[55][55][55][55];
ll dp[55][55];

int main(){
    int h,w; cin >> h >> w;
    vs s(h); rep(i,h) cin >> s[i];
    ll INF = (ll)1e15+1;
    rep(i,h) s[i].push_back('+');
    s.push_back(string(w+1,'+'));
    rep(i,h) rep(j,w) rep(k,h) rep(l,w){
        dp[i][j] = mul[i][j][k][l] = 0;
    }
    dp[0][0] = 0;
    rep(i,h) rep(j,w) if((i+j)&1^1) mul[i][j][i][j] = s[i][j] - '0';
    rep(k,h) rep(l,w){
        if((k+l)&1) continue;
        rep(i,h) rep(j,w){
            if(i>k || j>l) continue;
            ll c = s[k][l] - '0';
            if(k>=2 && s[k-1][l] == '*') chmax(mul[i][j][k][l], min(INF, mul[i][j][k-2][l] * c));
            if(l>=2 && s[k][l-1] == '*') chmax(mul[i][j][k][l], min(INF, mul[i][j][k][l-2] * c));
            if(k>=1 && l>=1 && (s[k-1][l] == '*' || s[k][l-1] == '*')){
                chmax(mul[i][j][k][l], min(INF, mul[i][j][k-1][l-1] * c));
            }
        }
    }
    rep(k,h) rep(l,w){
        if((k+l)&1) continue;
        rep(i,h) rep(j,w){
            if(i>k || j>l) continue;
            ll res = min(INF, dp[i][j] + mul[i][j][k][l]);
            if(s[k+1][l] == '+') chmax(dp[k+2][l], res);
            if(s[k][l+1] == '+') chmax(dp[k][l+2], res);
            if(s[k+1][l] == '+' || s[k][l+1] == '+') chmax(dp[k+1][l+1], res);
        }
    }
    if(dp[h][w] == INF) dp[h][w] = -1;
    cout << dp[h][w] << endl;
}
accuracy: 1
time_ms: 10
memory_kb: 68840
final_rank: 12

code_snippet: #pragma GCC target("avx2")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
using namespace std;
#define DEBUG
#ifdef DEBUG
template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << '(' << p.first << ',' << p.second << ')';
    return os;
}
template <class T> ostream &operator<<(ostream &os, const vector<T> &v) {
    os << '{';
    for(int i = 0; i < (int)v.size(); i++) {
        if(i) { os << ','; }
        os << v[i];
    }
    os << '}';
    return os;
}
void debugg() { cerr << endl; }
template <class T, class... Args>
void debugg(const T &x, const Args &... args) {
    cerr << " " << x;
    debugg(args...);
}
#define debug(...)                                                             \
    cerr << __LINE__ << " [" << #__VA_ARGS__ << "]: ", debugg(__VA_ARGS__)
#define dump(x) cerr << __LINE__ << " " << #x << " = " << (x) << endl
#else
#define debug(...) (void(0))
#define dump(x) (void(0))
#endif
using namespace std;
typedef long long ll;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<char> vc;
typedef vector<string> vs;
typedef vector<bool> vb;
typedef vector<double> vd;
typedef pair<ll,ll> P;
typedef pair<int,int> pii;
typedef vector<P> vpl;
typedef tuple<ll,ll,ll> tapu;
#define rep(i,n) for(int i=0; i<(n); i++)
#define REP(i,a,b) for(int i=(a); i<(b); i++)
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
const int inf = (1<<30)-1;
const ll linf = 1LL<<61;
const int MAX = 510000;
int dy[8] = {0,1,0,-1,1,-1,-1,1};
int dx[8] = {-1,0,1,0,1,-1,1,-1};
const double pi = acos(-1);
const double eps = 1e-7;
template<typename T1,typename T2> inline bool chmin(T1 &a,T2 b){
	if(a>b){
		a = b; return true;
	}
	else return false;
}
template<typename T1,typename T2> inline bool chmax(T1 &a,T2 b){
	if(a<b){
		a = b; return true;
	}
	else return false;
}
template<typename T> inline void print(T &a){
    int sz = a.size();
    for(auto itr = a.begin(); itr != a.end(); itr++){
		cout << *itr;
        sz--;
        if(sz) cout << " ";
	}
    cout << "\n";
}
template<typename T1,typename T2> inline void print2(T1 a, T2 b){
	cout << a << " " << b << "\n";
}
template<typename T1,typename T2,typename T3> inline void print3(T1 a, T2 b, T3 c){
	cout << a << " " << b << " " << c << "\n";
}
void mark() {cout << "#" << "\n";}
ll pcount(ll x) {return __builtin_popcountll(x);}
//const int mod = 1e9 + 7;
const int mod = 998244353;
//#include <atcoder/all>
//using namespace atcoder;

ll mul[55][55][55][55];
ll dp[55][55];

int main(){
    int h,w; cin >> h >> w;
    vs s(h); rep(i,h) cin >> s[i];
    ll INF = 1e15;
    rep(i,h) s[i].push_back('+');
    s.push_back(string(w+1,'+'));
    rep(i,h) rep(j,w) rep(k,h) rep(l,w){
        dp[i][j] = mul[i][j][k][l] = 0;
    }
    dp[0][0] = 0;
    rep(i,h) rep(j,w) if((i+j)&1^1) mul[i][j][i][j] = s[i][j] - '0';
    rep(k,h) rep(l,w){
        if((k+l)&1) continue;
        rep(i,h) rep(j,w){
            if(i>k || j>l) continue;
            ll c = s[k][l] - '0';
            if(k>=2 && s[k-1][l] == '*') chmax(mul[i][j][k][l], min(INF, mul[i][j][k-2][l] * c));
            if(l>=2 && s[k][l-1] == '*') chmax(mul[i][j][k][l], min(INF, mul[i][j][k][l-2] * c));
            if(k>=1 && l>=1 && (s[k-1][l] == '*' || s[k][l-1] == '*')){
                chmax(mul[i][j][k][l], min(INF, mul[i][j][k-1][l-1] * c));
            }
        }
    }
    rep(k,h) rep(l,w){
        if((k+l)&1) continue;
        rep(i,h) rep(j,w){
            if(i>k || j>l) continue;
            ll res = min(INF, dp[i][j] + mul[i][j][k][l]);
            if(s[k+1][l] == '+') chmax(dp[k+2][l], res);
            if(s[k][l+1] == '+') chmax(dp[k][l+2], res);
            if(s[k+1][l] == '+' || s[k][l+1] == '+') chmax(dp[k+1][l+1], res);
        }
    }
    if(dp[h][w] == INF) dp[h][w] = -1;
    cout << dp[h][w] << endl;
}
accuracy: 0.9487179487179487
time_ms: 10
memory_kb: 68772
final_rank: 19

code_snippet: #include<bits/stdc++.h>
using namespace std;
#define ALL(x) begin(x),end(x)
#define rep(i,n) for(int i=0;i<(n);i++)
#define debug(v) cout<<#v<<":";for(auto x:v){cout<<x<<' ';}cout<<endl;
#define mod 1000000007
using ll=long long;
const int INF=1000000000;
const ll LINF=1001002003004005006ll;
int dx[]={1,0,-1,0},dy[]={0,1,0,-1};
// ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
template<class T>bool chmax(T &a,const T &b){if(a<b){a=b;return true;}return false;}
template<class T>bool chmin(T &a,const T &b){if(b<a){a=b;return true;}return false;}

struct IOSetup{
    IOSetup(){
        cin.tie(0);
        ios::sync_with_stdio(0);
        cout<<fixed<<setprecision(12);
    }
} iosetup;

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

// 2^127 = 170141183460469231731687303715884105728 ~ 10^38
 
ostream &operator<<(ostream &os,const __int128 &n){
    if(n==0){
        os<<0;
        return os;
    }
    __int128 num=n;
    bool neg=false;
    if(num<0)neg=true,num=-num;
    string res="";
    while(num>0){
        res.push_back('0'+num%10);
        num/=10;
    }
    if(neg) res.push_back('-');
    reverse(begin(res),end(res));
    os<<res;
    return os;
}

istream &operator>>(istream &is,__int128 &n){
    string s;
    is>>s;
    int idx=0;
    bool neg=false;
    if(s[0]=='-')neg=true,idx++;
    n=0;
    for(;idx<(int)s.size();idx++){
        n=10*n+s[idx]-'0';
    }
    if(neg) n=-n;
    return is;
}

__int128 abs128(__int128 x){
    return x<0?-x:x;
}
 
__int128 gcd128(__int128 a,__int128 b){
    if(a==0) return b;
    if(b==0) return a;
    return b>0?gcd128(b,a%b):a;
}
using int128=__int128;

int128 LIM=1000000000000000ll;

int128 mul(int128 a,int128 b){
    if(a*b>LIM) return LIM+1;
    return a*b;
}

int128 add(int128 a,int128 b){
    if(a+b>LIM) return LIM+1;
    return a+b;
}

// graph template
// ref : https://ei1333.github.io/library/graph/graph-template.cpp
template<typename T=int>
struct Edge{
    int from,to;
    T w;
    int idx;
    Edge()=default;
    Edge(int from,int to,T w=1,int idx=-1):from(from),to(to),w(w),idx(idx){}
    operator int() const{return to;}
};

template<typename T=int>
struct Graph{
    vector<vector<Edge<T>>> g;
    int V,E;
    Graph()=default;
    Graph(int n):g(n),V(n),E(0){}

    size_t size(){
        return g.size();
    }
    void resize(int k){
        g.resize(k);
    }
    inline const vector<Edge<T>> &operator[](int k)const{
        return (g.at(k));
    }
    inline vector<Edge<T>> &operator[](int k){
        return (g.at(k));
    }
    void add_directed_edge(int from,int to,T cost=1){
        g[from].emplace_back(from,to,cost,E++);
    }
    void add_edge(int from,int to,T cost=1){
        g[from].emplace_back(from,to,cost,E);
        g[to].emplace_back(to,from,cost,E++);
    }
    void read(int m,int pad=-1,bool weighted=false,bool directed=false){
        for(int i=0;i<m;i++){
            int u,v;cin>>u>>v;
            u+=pad,v+=pad;
            T w=T(1);
            if(weighted) cin>>w;
            if(directed) add_directed_edge(u,v,w);
            else         add_edge(u,v,w);
        }
    }
};

signed main(){
    int h,w;cin>>h>>w;
    vector<string> g(h);
    cin>>g;

    auto get=[&](int i,int j){
        return i*w+j;
    };

    if(h==1 and w==1){
        cout<<g[0][0]<<endl;
        return 0;
    }

    Graph<int128> G(h*w);

    using P=pair<int,int>;
    rep(i,h)rep(j,w){
        if((i==0 and j==0) or g[i][j]=='+'){
            int128 b=1;
            if(i==0 and j==0) b*=g[i][j]-'0';

            priority_queue<pair<int128,P>> que;
            vector<vector<int128>> d(h,vector<int128>(w,0));
            que.emplace(b,P(i,j));
            d[i][j]=b;

            while(!que.empty()){
                auto [cost,cur]=que.top();que.pop();
                auto [ci,cj]=cur;
                if(d[ci][cj]>cost) continue;
                if((ci!=i or cj!=j) and g[ci][cj]=='+') continue;

                if(ci+1<h){
                    auto nxtc=cost;
                    if(isdigit(g[ci+1][cj])) nxtc=mul(nxtc,g[ci+1][cj]-'0');
                    if(chmax(d[ci+1][cj],nxtc)) que.emplace(nxtc,P(ci+1,cj));
                }
                if(cj+1<w){
                    auto nxtc=cost;
                    if(isdigit(g[ci][cj+1])) nxtc=mul(nxtc,g[ci][cj+1]-'0');
                    if(chmax(d[ci][cj+1],nxtc)) que.emplace(nxtc,P(ci,cj+1));
                }
            }
            
            for(int ni=i;ni<h;ni++){
                for(int nj=j;nj<w;nj++){
                    if(ni==i and nj==j) continue;
                    if(g[ni][nj]=='+') G.add_directed_edge(get(i,j),get(ni,nj),d[ni][nj]);
                    if(ni==h-1 and nj==w-1) G.add_directed_edge(get(i,j),get(ni,nj),d[ni][nj]);
                }
            }
        }
    }

    vector<int128> dp(h*w,0);
    rep(i,h*w){
        for(auto &e:G[i]) chmax(dp[e],add(dp[i],e.w));
    }

    // rep(i,h){
    //     rep(j,w){
    //         cout<<dp[get(i,j)]<<" ";
    //     }
    //     cout<<endl;
    // }

    if(dp[h*w-1]>LIM) cout<<-1<<endl;
    else              cout<<dp[h*w-1]<<endl;
    return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 25612
final_rank: 5

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

#define For(i, a, b) for (int i = (int)(a); i < (int)(b); ++i)
#define rFor(i, a, b) for (int i = (int)(a)-1; i >= (int)(b); --i)
#define rep(i, n) For((i), 0, (n))
#define rrep(i, n) rFor((i), (n), 0)
#define fi first
#define se second

using namespace std;

typedef long long lint;
typedef unsigned long long ulint;
typedef pair<int, int> pii;
typedef pair<lint, lint> pll;

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

template <class T>
T div_floor(T a, T b) {
    if (b < 0) a *= -1, b *= -1;
    return a >= 0 ? a / b : (a + 1) / b - 1;
}
template <class T>
T div_ceil(T a, T b) {
    if (b < 0) a *= -1, b *= -1;
    return a > 0 ? (a - 1) / b + 1 : a / b;
}

template <typename T>
struct coord_comp {
    vector<T> v;
    bool sorted = false;

    coord_comp() {}

    int size() { return v.size(); }

    void add(T x) { v.push_back(x); }

    void build() {
        sort(v.begin(), v.end());
        v.erase(unique(v.begin(), v.end()), v.end());
        sorted = true;
    }

    int get_idx(T x) {
        assert(sorted);
        return lower_bound(v.begin(), v.end(), x) - v.begin();
    }
};

constexpr lint mod = 1000000007;
constexpr lint INF = mod * mod;
constexpr int MAX = 200010;

int dx[2] = {0, -1};
int dy[2] = {-1, 0};
lint dp[50][50], mul[50][50][50][50];
constexpr lint LIM = 1000000000000000LL;
int h, w;
char c[50][50];

lint dfs(int i, int j, int k, int l) {
    if (mul[i][j][k][l] >= 0) return mul[i][j][k][l];
    if (i == k && j == l) return mul[i][j][k][l] = c[i][j] - '0';

    rep(t, 2) {
        int x = k + dx[t], y = l + dy[t];
        if (x >= i && y >= j && c[x][y] == '*') {
            rep(u, 2) {
                int nx = x + dx[u], ny = y + dy[u];
                if (nx >= i && ny >= j) {
                    lint tmp = dfs(i, j, nx, ny);
                    if (tmp >= 0) chmax(mul[i][j][k][l], tmp * (c[k][l] - '0'));
                    chmin(mul[i][j][k][l], LIM);
                }
            }
        }
    }
    return mul[i][j][k][l];
}

int main() {
    scanf("%d%d", &h, &w);
    rep(i, h) rep(j, w) scanf(" %c", &c[i][j]);

    rep(i, h) rep(j, w) rep(k, h) rep(l, w) {
        mul[i][j][k][l] = -1;
        dp[i][j] = -1;
    }
    rep(i, h) rep(j, w) if ((i + j) % 2 == 0) {
        rep(k, h) rep(l, w) if ((k + l) % 2 == 0) dfs(i, j, k, l);
    }

    dp[0][0] = c[0][0] - '0';
    rep(i, h) rep(j, w) if ((i + j) % 2 == 0 && dp[i][j] < 0) {
        dp[i][j] = mul[0][0][i][j];
        rep(k, h + 1) rep(l, w + 1) if (mul[k][l][i][j] > 0) {
            if (mul[k][l][i][j] >= LIM) {
                puts("-1");
                return 0;
            }
            rep(t, 2) {
                int x = k + dx[t], y = l + dy[t];
                if (x >= 0 && y >= 0 && c[x][y] == '+') {
                    rep(u, 2) {
                        int nx = x + dx[u], ny = y + dy[u];
                        if (nx >= 0 && ny >= 0) {
                            chmax(dp[i][j], dp[nx][ny] + mul[k][l][i][j]);
                            if (dp[i][j] >= LIM) {
                                puts("-1");
                                return 0;
                            }
                        }
                    }
                }
            }
        }
    }
    printf("%lld\n", dp[h - 1][w - 1]);
}
accuracy: 0.6153846153846154
time_ms: 1580
memory_kb: 36976
final_rank: 20

code_snippet: #include <bits/stdc++.h>
using namespace std;
const long long INF = 1000000000000001;
int main(){
  int H, W;
  cin >> H >> W;
  vector<vector<char>> a(H, vector<char>(W));
  for (int i = 0; i < H; i++){
    for (int j = 0; j < W; j++){
      cin >> a[i][j];
    }
  }
  long long ans = 0;
  vector<vector<long long>> dp(H, vector<long long>(W, 0));
  for (int i = 0; i < H; i++){
    for (int j = 0; j < W; j++){
      if ((i + j) % 2 == 0){
        vector<vector<long long>> dp2(H + 1, vector<long long>(W + 1, 0));
        dp2[i][j] = a[i][j] - '0';
        for (int k = i; k < H; k++){
          for (int l = j; l < W; l++){
            if ((k + l) % 2 == 0){
              if (k < H - 1){
                if (a[k + 1][l] == '*'){
                  if (k < H - 2){
                    dp2[k + 2][l] = max(dp2[k + 2][l], min(dp2[k][l] * (a[k + 2][l] - '0'), INF));
                  }
                  if (l < W - 1){
                    dp2[k + 1][l + 1] = max(dp2[k + 1][l + 1], min(dp2[k][l] * (a[k + 1][l + 1] - '0'), INF));
                  }
                }
              }
              if (l < W - 1){
                if (a[k][l + 1] == '*'){
                  if (k < H - 1){
                    dp2[k + 1][l + 1] = max(dp2[k + 1][l + 1], min(dp2[k][l] * (a[k + 1][l + 1] - '0'), INF));
                  }
                  if (l < W - 2){
                    dp2[k][l + 2] = max(dp2[k][l + 2], min(dp2[k][l] * (a[k][l + 2] - '0'), INF));
                  }
                }
              }
            }
          }
        }
        for (int k = i; k < H; k++){
          for (int l = j; l < W; l++){
            if ((k + l) % 2 == 0){
              if (k == H - 1 && l == W - 1){
                ans = max(ans, min(dp[i][j] + dp2[k][l], INF));
              }
              if (k < H - 1){
                if (a[k + 1][l] == '+'){
                  if (k < H - 2){
                    dp[k + 2][l] = max(dp[k + 2][l], min(dp[i][j] + dp2[k][l], INF));
                  }
                  if (l < W - 1){
                    dp[k + 1][l + 1] = max(dp[k + 1][l + 1], min(dp[i][j] + dp2[k][l], INF));
                  }
                }
              }
              if (l < W - 1){
                if (a[k][l + 1] == '+'){
                  if (k < H - 1){
                    dp[k + 1][l + 1] = max(dp[k + 1][l + 1], min(dp[i][j] + dp2[k][l], INF));
                  }
                  if (l < W - 2){
                    dp[k][l + 2] = max(dp[k][l + 2], min(dp[i][j] + dp2[k][l], INF));
                  }
                }
              }
            }
          }
        }
      }
    }
  }
  if (ans == INF){
    cout << -1 << endl;
  } else {
    cout << ans << endl;
  }
}
accuracy: 1
time_ms: 10
memory_kb: 3176
final_rank: 1