Route Calculator |
Time Limit: 10000ms, Special Time Limit:25000ms, Memory Limit:524288KB |
Total submit users: 9, Accepted users: 2 |
Problem 14108 : No special judgement |
Problem description |
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 1015 or less, print the value. Otherwise, print -1. |
Input |
The input consists of a single test case in the format below. H W a1,1...a1,W ... aH,1...aH,W The first line consists of two integers H and W(1 ≤ H,W ≤ 50). It is guaranteed that H+W is even. The following H lines represent the characters on the grid. ai,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+j is odd. |
Output |
Print the answer in one line. |
Sample Input |
Sample Input 1 3 3 1+2 +9* 1*5 Sample Input 2 1 31 9*9*9*9*9*9*9*9*9*9*9*9*9*9*9*9 Sample Input 3 5 5 2+2+1 +1+1+ 1+2+2 +1+1+ 1+1+2 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 |
Sample Output |
Output for Sample Input 1 46 Output for Sample Input 2 -1 Output for Sample Input 3 10 Output for Sample Input 4 86408 |
Judge Tips |
The 1st case,The maximum value is obtained by passing through the following cells:(1,1) ,(2,1) ,(2,2) ,(2,3) ,(3,3) . The 2nd case,You can obtain 916, but it's too large. |
Problem Source |
JAG Practice Contest for ACM-ICPC Asia Regional 2017, AtCoder, 2017-09-24 |
题意:有一个n*m的矩阵,矩阵由数字和+,*组成,保证数字周围是运算符,运算符周围是数字,求一条路径从左上角到右上角,运算结果最大,注意如果结果大于1e15输出-1
题解:本题跟CCF的走大路走小路很类似,首先我们将连乘预处理,得到(i,j) -> (u, v)连乘的最大值,然后进行一次简单dp即可。
我们用a[i][j][k][l]记录从(i, j)到(k,l)连乘的最大值,用b[i][j]记录从起点到(i, j)的最大值,c[i][j]记录原矩阵的值,则对于当前点(i,j)我们可以得到,如果其左边有加号,则取b[i - 1][j - 1]和b[i][j - 2]的较大值,若上面有加号,则取b[i - 1][j - 1][i - 2][j]的较大值,将之前取得的较大值再取较大值,与c[i][j]相加更新当前的b[i][j], 同时如果之前有点能连乘到(i, j),假设其为(u, v),则用
b[u][v] - c[u][v] + a[u][v][i][j]来跟当前b[i][j]比较,取较大值
以上
AC代码
#include <stdio.h>
#include <iostream>
#include <queue>
#define ll __int64
using namespace std;
const ll maxn = 55, inf = 1e15;
char map1[maxn][maxn];
ll a[maxn][maxn][maxn][maxn] = {0}, b[maxn][maxn], c[maxn][maxn], d[maxn][maxn], vis[55 * 55] = {0};
vector<ll> s[55 * 55];
bool shu(char x){
if(x >= '0' && x <= '9')
return true;
return false;
}
int main(){
ll n, m;
scanf("%I64d %I64d", &n, &m);
for(ll i = 0; i < n; i++){
scanf("%s", map1[i]);
for(ll j = 0; j < m; j++){
if(map1[i][j] >= '0' && map1[i][j] <= '9'){
b[i][j] = a[i][j][i][j] = c[i][j] = map1[i][j] - '0';
}
}
}
for(ll i = 0; i < n; i++){
for(ll j = 0; j < m; j++){
for(ll k = i; k < n; k++){
for(ll l = j; l < m; l++){
if(shu(map1[i][j]) && shu(map1[k][l]) && (k != i || l != j)){
ll temp = 1;
ll ff = 0;
if(k - 1 >= i && map1[k - 1][l] == '*'){
if(k - 2 >= i){
temp = max(temp, a[i][j][k - 2][l]);
}
ff = 1;
}
if(l - 1 >= j && map1[k][l - 1] == '*'){
if(l - 2 >= j){
temp = max(temp, a[i][j][k][l - 2]);
}
ff =1;
}
if((l - 1 >= j) && (k - 1 >= i) && (map1[k - 1][l] == '*' || map1[k][l - 1] == '*')){
temp = max(temp, a[i][j][k - 1][l - 1]);
ff = 1;
}
if(ff == 0)
continue;
a[i][j][k][l] = b[k][l] * temp;
if(a[i][j][k][l] > inf){
printf("-1");
return 0;
}
if(temp != 1){
s[k * maxn + l].push_back(i * maxn + j);
}
}
}
}
}
}
for(ll i = 0; i < n; i++){
for(ll j = 0; j < m; j++){
ll temp = 0;
if(!shu(map1[i][j]))
continue;
if(i - 1 >= 0 && map1[i - 1][j] == '+'){
if(i - 2 >= 0){
temp = max(temp, c[i][j] + b[i - 2][j]);
}
}
if(j - 1 >= 0 && map1[i][j - 1] == '+'){
if(j - 2 >= 0){
temp = max(temp, c[i][j] + b[i][j - 2]);
}
}
if(j - 1 >= 0 && i - 1 >= 0 && (map1[i - 1][j] == '+' || map1[i][j - 1] == '+')){
temp = max(temp, c[i][j] + b[i - 1][j - 1]);
}
if(s[i * maxn + j].size()){
for(int k = 0; k < s[i * maxn + j].size(); k++){
int v = s[i * maxn + j][k];
temp = max(temp, b[v / maxn][v % maxn] - c[v/maxn][v%maxn] + a[v / maxn][v % maxn][i][j]);
}
}
b[i][j] = max(temp, c[i][j]);
if(b[i][j] > inf){
printf("-1\n");
return 0;
}
}
}
printf("%I64d\n", b[n - 1][m - 1]);
return 0;
}