题目描述
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.
输入
he 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 H integers 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+1 is odd.
输出
Print the answer in one line.
思路:
若本题将运算符号全部改成加号,仔细想一下,就是一个dp的模版题。关键是现在运算符号有加号和乘号。这里我们开数组d[i][j][u][v],表示从点(i,j)到点(u,v)连续乘积的最大值,num[i][j]表示当前位置上的原本值。
那么该dp方程为:设dp[i][j]表示从原点到点(i,j)运算的最大值。则对于当前点(i,j),1.若其左边有加号,则取dp[i - 1][j - 1]和dp[i][j - 2]的较大值。2.若上面有加号,则取dp[i - 1][j - 1]和dp[i - 2][j]的较大值,将之前两种情况取得的较大值再取较大值,与num[i][j]相加更新当前的dp[i][j]。
此外若之前有点能连乘到(i, j),假设其为(u, v),则用dp[u][v] - num[u][v] + d[u][v][i][j]来跟当前dp[i][j]比较,取较大值
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define ll long long
#define inf 1e15
#define mod 55
using namespace std;
char mp[100][100];
ll dp[100][100],d[55][55][55][55],num[100][100];
bool ok(char ch){
if(ch>='0'&&ch<='9')
return true;
else return 0;
}
vector<ll>s[1008611];
int main(){
ll h,w;
scanf("%lld%lld",&h,&w);
for(int i=0;i<h;i++){
scanf("%s",mp[i]);
}
for(int i=0;i<h;i++){
for(int j=0;j<w;j++){
if(ok(mp[i][j])){
dp[i][j]=mp[i][j]-'0';
d[i][j][i][j]=mp[i][j]-'0';
num[i][j]=mp[i][j]-'0';
}
}
}
for(int i=0;i<h;i++){
for(int j=0;j<w;j++){
for(int u=i;u<h;u++){
for(int v=j;v<w;v++){
if(ok(mp[i][j]) && ok(mp[u][v]) && (u!=i||v!=j)){
ll temp = 1;
ll flag = 0;
if(u - 1 >= i && mp[u - 1][v] == '*'){
if(u-2>=i){
temp = max(temp, d[i][j][u - 2][v]);
}
flag = 1;
}
if(v-1>=j&&mp[u][v-1]=='*'){
if(v-2>=j){
temp=max(temp, d[i][j][u][v-2]);
}
flag =1;
}
if((v - 1 >= j) && (u - 1 >= i) &&(mp[u - 1][v]=='*'||mp[u][v -1]=='*')){
temp = max(temp, d[i][j][u- 1][v-1]);
flag = 1;
}
if(flag){
d[i][j][u][v] = dp[u][v]*temp;
if(d[i][j][u][v]>inf){
printf("-1\n");
return 0;
}
if(temp != 1){
s[u*mod+v].push_back(i*mod+j);//记录点(u,v,i,j),以便下面找从(i,j)到(u,v)连乘的值
}
}
}
}
}
}
}
for(int i=0;i<h;i++){
for(ll j=0;j<w;j++){
ll temp = 0;
if(!ok(mp[i][j]))
continue;
if(i-1>=0&&mp[i-1][j]=='+'){
if(i-2>=0){
temp = max(temp, num[i][j] +dp[i - 2][j]);
}
}
if(j - 1 >= 0 && mp[i][j - 1]=='+'){
if(j-2>=0){
temp = max(temp,num[i][j]+dp[i][j - 2]);
}
}
if(j-1>=0&&i-1>= 0&&(mp[i - 1][j]=='+'||mp[i][j - 1]=='+')){
temp=max(temp,num[i][j]+dp[i - 1][j - 1]);
}
if(s[i*mod+j].size()){
for(int k=0;k<s[i*mod+ j].size(); k++){
ll beg,en;
ll v = s[i * mod+ j][k];
beg=v/mod;en=v%mod;
temp = max(temp, dp[beg][en]-num[beg][en]+d[beg][en][i][j]);
}
}
dp[i][j] = max(temp, num[i][j]);
if(dp[i][j] > inf){
printf("-1\n");
return 0;
}
}
}
printf("%lld\n",dp[h-1][w-1]);
return 0;
}