2018暑假校内第一次比赛

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;
}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值