import java.util.*
import kotlin.collections.ArrayList

fun main(args: Array<String>?): Unit {
    val (h, w) = readLine()!!.trim().split(' ').map(String::toInt)
    val state = Array(h){
        readLine()!!.trim().toCharArray().map{
            when(it){
                '+' -> Cell.Operation.Add
                '*' -> Cell.Operation.Mul
                else -> Cell.Digit(it - '0')
            }
        }.toTypedArray()
    }
    val memo = Array(h){Array(w){-1L as Long?}}
    val res = search(0, 0, state, memo) ?: -1
    println(res)
}

sealed class Cell {
    sealed class Operation(val op: (Long?, Long?) -> Long?): Cell() {//TODO(OVERFLOW)
        object Add: Operation({aa, bb -> aa?.let{a -> bb?.let{b -> a + b}}?.takeIf{it <= 1000000000000000L}})
        object Mul: Operation({aa, bb ->
            if (aa == null || bb == null) null
            else if (java.lang.Math.log10(aa.toDouble()) + java.lang.Math.log10(bb.toDouble()) > 15) null
            else (aa * bb).takeIf{it <= 1000000000000000L}
        })
    }
    data class Digit(val digit: Int): Cell()
}
fun optMax(a: Long?, b: Long?): Long? {
    return if (a == null || b == null) null else java.lang.Math.max(a, b)
}
fun search(i: Int, j: Int, state: Array<Array<Cell>>, memo: Array<Array<Long?>>): Long? {
    if (i !in memo.indices || j !in memo[i].indices) return 0L
    if (memo[i][j] != -1L) return memo[i][j]
    val cache = Array(memo.size){Array(memo.first().size){-1L as Long?}}.also{it[i][j] = (state[i][j] as Cell.Digit).digit.toLong()}
    val queue: Queue<Pair<Int, Int>> = ArrayDeque<Pair<Int, Int>>().apply{add(Pair(i, j))}
    var result = 0L as Long?
    while (queue.isNotEmpty()) {
        val (y, x) = queue.poll()
        val cell = state[y][x]
        when(cell) {
            is Cell.Digit -> {
                result = optMax(result, cache[y][x])
                if (y + 1 in memo.indices) {
                    if (cache[y + 1][x] == -1L) queue.add(Pair(y + 1, x))
                    cache[y + 1][x] = optMax(cache[y + 1][x], cache[y][x])
                }
                if (x + 1 in cache[y].indices) {
                    if (cache[y][x + 1] == -1L) queue.add(Pair(y, x + 1))
                    cache[y][x + 1] = optMax(cache[y][x + 1], cache[y][x])
                }
            }
            is Cell.Operation.Add -> {
                result = optMax(result, optMax(cell.op(cache[y][x], search(y + 1, x, state, memo)), cell.op(cache[y][x], search(y, x + 1, state, memo))))
            }
            is Cell.Operation.Mul -> {
                if (y + 1 in cache.indices) {
                    if (cache[y + 1][x] == -1L) queue.add(Pair(y + 1, x))
                    cache[y + 1][x] = optMax(cache[y + 1][x], cell.op((state[y + 1][x] as Cell.Digit).digit.toLong(), cache[y][x]))
                }
                if (x + 1 in cache[y].indices) {
                    if (cache[y][x + 1] == -1L) queue.add(Pair(y, x + 1))
                    cache[y][x + 1] = optMax(cache[y][x + 1], cell.op((state[y][x + 1] as Cell.Digit).digit.toLong(), cache[y][x]))
                }
            }
        }
    }
    memo[i][j] = result
    return result
}

