Codeforces 935E-Fafa and Ancient Mathematics

Fafa and Ancient Mathematics
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Ancient Egyptians are known to have understood difficult concepts in mathematics. The ancient Egyptian mathematician Ahmes liked to write a kind of arithmetic expressions on papyrus paper which he called as Ahmes arithmetic expression.

An Ahmes arithmetic expression can be defined as:

  • "d" is an Ahmes arithmetic expression, where d is a one-digit positive integer;
  • "(E1op E2)" is an Ahmes arithmetic expression, where E1 and E2 are valid Ahmes arithmetic expressions (without spaces) and op is either plus ( + ) or minus ( - ).
For example  5(1-1) and  ((1+(2-3))-5) are valid Ahmes arithmetic expressions.

On his trip to Egypt, Fafa found a piece of papyrus paper having one of these Ahmes arithmetic expressions written on it. Being very ancient, the papyrus piece was very worn out. As a result, all the operators were erased, keeping only the numbers and the brackets. Since Fafa loves mathematics, he decided to challenge himself with the following task:

Given the number of plus and minus operators in the original expression, find out the maximum possible value for the expression on the papyrus paper after putting the plus and minus operators in the place of the original erased operators.

Input

The first line contains a string E (1 ≤ |E| ≤ 104) — a valid Ahmes arithmetic expression. All operators are erased and replaced with '?'.

The second line contains two space-separated integers P and M (0 ≤ min(P, M) ≤ 100) — the number of plus and minus operators, respectively.

It is guaranteed that P + M =  the number of erased operators.

Output

Print one line containing the answer to the problem.

Examples
input
Copy
(1?1)
1 0
output
2
input
Copy
(2?(1?2))
1 1
output
1
input
Copy
((1?(5?7))?((6?2)?7))
3 2
output
18
input
Copy
((1?(5?7))?((6?2)?7))
2 3
output
16
Note
  • The first sample will be (1 + 1)  =  2.
  • The second sample will be (2 + (1 - 2))  =  1.
  • The third sample will be ((1 - (5 - 7)) + ((6 + 2) + 7))  =  18.
  • The fourth sample will be ((1 + (5 + 7)) - ((6 - 2) - 7))  =  16.

题意:给出一个算式,由括号、小于10的正整数和问号组成,问号是算式中的符号,现给出原式中加号的个数p和减号的个数m,对于所有填放方式对应的结果,求最大值。

解题思路:可以把这个算式化成一个二叉树,叶子节点是一个数,非叶子节点表示一个符号,当一个非叶子结点填加号时,就需要最大化左右子树的值,当一个非叶子结点填减号时,就需要最大化左子树值,最小化右子树值。树形dp可以解决这个问题,可以用dp[i][j][k][0/1]示第i个点及其子树中填了j个加号,k个负号所能得到的最大 / 最小值,但是这样开数组开不下,但其实加号和减号数量可以互相转换,所以去掉加号或减号中的一维即可。


#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <vector>
#include <bitset>
#include <functional>

using namespace std;

#define LL long long     
const int INF = 0x3f3f3f3f;

int dp[2][10010][110];
char ch[10010];
int son[10010][2], cnt, fa[10010], p, m, pre, mi;

void dfs(int x)
{
	if (!son[x][0]) return;
	int l = son[x][0], r = son[x][1];
	dfs(l), dfs(r);
	for (int i = 0; i <= mi; i++)
	{
		for (int j = 0; i + j <= mi; j++)
		{
			dp[0][x][i + j + (p < m)] = max(dp[0][x][i + j + (p < m)], dp[0][l][i] + dp[0][r][j]);
			dp[0][x][i + j + (p >= m)] = max(dp[0][x][i + j + (p >= m)], dp[0][l][i] - dp[1][r][j]);
			dp[1][x][i + j + (p < m)] = min(dp[1][x][i + j + (p < m)], dp[1][l][i] + dp[1][r][j]);
			dp[1][x][i + j + (p >= m)] = min(dp[1][x][i + j + (p >= m)], dp[1][l][i] - dp[0][r][j]);
		}
	}
}

int main()
{
	while (~scanf("%s", ch))
	{
		scanf("%d%d", &p, &m);
		mi = min(p, m);
		int len = strlen(ch);
		cnt = pre = 1;
		son[1][0] = son[1][1] = 0;
		memset(dp[0], -INF, sizeof dp[0]);
		memset(dp[1], INF, sizeof dp[1]);
		for (int i = 0; i < len; i++)
		{
			if (ch[i] == '(' || ch[i] == '?')
			{
				son[pre][son[pre][0] ? 1 : 0] = ++cnt;
				son[cnt][0] = son[cnt][1] = 0;
				fa[cnt] = pre;
				pre = cnt;
			}
			else if (ch[i] == ')') pre = fa[pre];
			else
			{
				dp[0][cnt][0] = dp[1][cnt][0] = ch[i] - '0';
				pre = fa[pre];
			}
		}
		dfs(1);
		printf("%d", dp[0][1][mi]);
	}
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值