CF935E Fafa and Ancient Mathematics

原题链接:http://codeforces.com/problemset/problem/935/E

Fafa and Ancient Mathematics

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 d ” is an Ahmes arithmetic expression, where d is a one-digit positive integer;
(E1opE2) ( E 1   o p   E 2 ) ” is an Ahmes arithmetic expression, where E1 E 1 and E2 E 2 are valid Ahmes arithmetic expressions (without spaces) and op o p is either plus ( + +  ) or minus ( ).
For example 5,(11) 5 , ( 1 − 1 ) and ((1+(23))5) ( ( 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) E ( 1   ≤   | E |   ≤   10 4 ) — a valid Ahmes arithmetic expression. All operators are erased and replaced with ‘?’.

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

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

Output

Print one line containing the answer to the problem.

Examples
input

(1?1)
1 0

output

2

input

(2?(1?2))
1 1

output

1

input

((1?(5?7))?((6?2)?7))
3 2

output

18

input

((1?(5?7))?((6?2)?7))
2 3

output

16

Note

The first sample will be (1+1)=2 ( 1   +   1 )     =     2 .

The second sample will be (2+(12))=1 ( 2   +   ( 1   −   2 ) )     =     1 .

The third sample will be ((1(57))+((6+2)+7))=18 ( ( 1   −   ( 5   −   7 ) )   +   ( ( 6   +   2 )   +   7 ) )     =     18 .

The fourth sample will be ((1+(5+7))((62)7))=16 ( ( 1   +   ( 5   +   7 ) )   −   ( ( 6   −   2 )   −   7 ) )     =     16 .

题目大意

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

题解

这里要用到一种将算式转化为二叉树的技巧,每个叶子节点为算式的初始数值,非叶子节点则为运算符号,样例 2 2 转换出的二叉树如图所示:

1.png

这样转化成二叉树之后,我们就可以做树形dp了,最简单的思路就是用 dp[i][j][k][0/1] d p [ i ] [ j ] [ k ] [ 0 / 1 ] 表示对于第 i i 个点,它的子树中使用了j个加号, k k 个减号时子树运算式的最大/最小值。

但是,这种做法需要O(|E|×P×M)的空间,似乎开不下来,但是题目的数据范围 (0min(P,M)100) ( 0   ≤   m i n ( P ,   M )   ≤   100 ) 似乎在暗示些什么。那么我们不妨把加号和减号的两维合并成一维,只记录数量较少的符号作为一维即可。

代码
#include<bits/stdc++.h>
#define ls son[v][0]
#define rs son[v][1]
using namespace std;
const int M=1e4+5;
int son[M][2],dad[M],dp[M][105][2],add,sub,len,minn,tot=1,pre=1;
char ch[M];
void build()
{
    len=strlen(ch+1),minn=min(add,sub);
    for(int i=1;i<M;++i)for(int j=0;j<=minn;++j)dp[i][j][0]=-1e9,dp[i][j][1]=1e9;
    for(int i=1;i<=len;++i)
    if(ch[i]=='('||ch[i]=='?')son[pre][son[pre][0]?1:0]=++tot,dad[tot]=pre,pre=tot;
    else if(ch[i]==')')pre=dad[pre];
    else dp[tot][0][0]=dp[tot][0][1]=ch[i]-'0',pre=dad[pre];
}
void dfs(int v)
{
    if(!ls)return;dfs(ls);dfs(rs);
    for(int i=0;i<=minn;++i)for(int j=0;i+j<=minn;++j)
    dp[v][i+j+(add<sub)][0]=max(dp[v][i+j+(add<sub)][0],dp[ls][i][0]+dp[rs][j][0]),
    dp[v][i+j+(add>=sub)][0]=max(dp[v][i+j+(add>=sub)][0],dp[ls][i][0]-dp[rs][j][1]),
    dp[v][i+j+(add<sub)][1]=min(dp[v][i+j+(add<sub)][1],dp[ls][i][1]+dp[rs][j][1]),
    dp[v][i+j+(add>=sub)][1]=min(dp[v][i+j+(add>=sub)][1],dp[ls][i][1]-dp[rs][j][0]);
}
void in(){scanf("%s%d%d",ch+1,&add,&sub);}
void ac(){build();dfs(1);printf("%d",dp[1][minn][0]);}
int main(){in();ac();}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ShadyPi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值