Codeforces 935E Fafa and Ancient Mathematics(表达式转树 + 树型DP)
题目链接 Codeforces Round #465 (Div. 2) Problem E
题意 给定一个表达式,然后用$P$个加号和$M$个减号填充所有的问号(保证问号个数等于$P + M$)
求可以形成的表达式的最大值。
先把表达式转成一棵树,然后在树上DP。
题目保证了$min(P, M) <= 100$, 为了提高效率,我们选择用少的运算符号作为DP的第二维。
对$P$和$M$的大小关系进行分类讨论。
当$P < M$时,
设$f[i][j]$表示$i$代表的子树里面填$j$个加号能得到的结果的最大值。
$c[i][j]$表示$i$代表的子树里面填$j$个减号能得到的结果的最小值。
那么转移就是
$f[x][i+j+1] = max(f[x][i+j+1], f[l][i] + l[r][j])$
$f[x][i+j] = max(f[x][i+j], f[l][i] - c[r][j])$
$c[x][i+j+1] = min(c[x][i+j+1], c[l][i] + c[r][j])$
$c[x][i+j] = min(c[x][i+j], c[l][i] - f[r][j])$
当$P > M$时,
设$f[i][j]$表示$i$代表的子树里面填$j$个加号能得到的结果的最大值。
$c[i][j]$表示$i$代表的子树里面填$j$个减号能得到的结果的最小值。
设个时候转移方程为
$f[x][i+j] = max(f[x][i+j], f[l][i] + l[r][j])$
$f[x][i+j+1] = max(f[x][i+j+1], f[l][i] - c[r][j])$
$c[x][i+j] = min(c[x][i+j], c[l][i] + c[r][j])$
$c[x][i+j+1] = min(c[x][i+j+1], c[l][i] - f[r][j])$
程序里把两种情况合起来写了,看起来更加简洁。
#include <bits/stdc++.h> using namespace std; #define rep(i, a, b) for (int i(a); i <= (b); ++i)
#define dec(i, a, b) for (int i(a); i >= (b); --i)
#define MP make_pair
#define fi first
#define se second typedef long long LL; const int N = 1e4 + 10;
const int M = 105;
const int inf = 1e9; char st[N];
int val[N];
int p, m, n;
int f[N][M], c[N][M];
vector <int> v[N];
stack <int> stk; inline void upmax(int &a, int b){ a = max(a, b);}
inline void upmin(int &a, int b){ a = min(a, b);} void dfs(int x, int t){
rep(i, 0, M - 1) f[x][i] = -inf, c[x][i] = inf;
if (val[x]){
f[x][0] = c[x][0] = val[x];
return;
} int l = v[x][0], r = v[x][1];
dfs(l, t), dfs(r, t); rep(i, 0, M - 1) if (f[l][i] > -inf){
rep(j, 0, M - 1) if (f[r][j] > -inf){
upmax(f[x][i + j + t], f[l][i] + f[r][j]);
upmax(f[x][i + j + (t ^ 1)], f[l][i] - c[r][j]);
upmin(c[x][i + j + t], c[l][i] + c[r][j]);
upmin(c[x][i + j + (t ^ 1)], c[l][i] - f[r][j]);
}
}
} int main(){ scanf("%s%d%d", st, &p, &m); for (int i = 0; st[i]; ++i){
if (st[i] == '(') stk.push(++n);
else if (st[i] == ')'){
int t = stk.top();
stk.pop();
if (!stk.empty()) v[stk.top()].push_back(t);
} else if (st[i] >= '1' && st[i] <= '9'){
if (stk.empty()) return 0 * printf("%d\n", st[i] - '0');
v[stk.top()].push_back(++n);
val[n] = st[i] - '0';
}
} dfs(1, p < m);
printf("%d\n", f[1][min(p, m)]);
return 0;
}
Codeforces 935E Fafa and Ancient Mathematics(表达式转树 + 树型DP)的更多相关文章
- Codeforces 935E Fafa and Ancient Mathematics dp
Fafa and Ancient Mathematics 转换成树上问题dp一下. #include<bits/stdc++.h> #define LL long long #define ...
- CodeForces 935E Fafa and Ancient Mathematics (树形DP)
题意:给定一个表达式,然后让你添加 n 个加号,m 个减号,使得表达式的值最大. 析:首先先要建立一个表达式树,这个应该很好建立,就不说了,dp[u][i][0] 表示 u 这个部分表达式,添加 i ...
- 【学术篇】CF935E Fafa and Ancient Mathematics 树形dp
前言 这是一道cf的比赛题.. 比赛的时候C题因为自己加了一个很显然不对的特判WA了7次但找不出原因就弃疗了... 然后就想划水, 但是只做了AB又不太好... 估计rating会掉惨 (然而事实证明 ...
- 2018.12.12 codeforces 935D. Fafa and Ancient Alphabet(概率dp)
传送门 概率dp水题. 题意简述:给你数字表的大小和两个数列,数列中为0的数表示不确定,不为0的表示确定的,求第一个数列字典序比第二个数列大的概率. fif_ifi表示第i ni~ ni n位第一个 ...
- Codeforces 935D Fafa and Ancient Alphabet
题目链接 题意 给定两个\(n\)位的\(m\)进制数\(s1,s2\),所有出现的\(0\)均可等概率地被其他数字替换,求\(s1\gt s2\)的概率. 思路 从高位到低位,根据每一位上相应的\( ...
- [Codeforces 464E] The Classic Problem(可持久化线段树)
[Codeforces 464E] The Classic Problem(可持久化线段树) 题面 给出一个带权无向图,每条边的边权是\(2^{x_i}(x_i<10^5)\),求s到t的最短路 ...
- Codeforces Good Bye 2015 D. New Year and Ancient Prophecy 后缀数组 树状数组 dp
D. New Year and Ancient Prophecy 题目连接: http://www.codeforces.com/contest/611/problem/C Description L ...
- Codeforces 552E - Vanya and Brackets【表达式求值】
给一个只有加号和乘号的表达式,要求添加一对括号使得最后结果最大.表达式长度5000,乘号最多12个,表达式中数字只有1位. 左括号一定在乘号右边,右括号一定在乘号左边,因为如果不是这样的话,一定可以调 ...
- codeforces 552 E. Vanya and Brackets 表达式求值
题目链接 讲道理距离上一次写这种求值的题已经不知道多久了. 括号肯定是左括号在乘号的右边, 右括号在左边. 否则没有意义. 题目说乘号只有15个, 所以我们枚举就好了. #include <io ...
随机推荐
- runtime如何通过selector找到对应的IMP地址?(分别考虑类方法和实例方法)
每一个类对象中都一个对象方法列表(对象方法缓存) 类方法列表是存放在类对象中isa指针指向的元类对象中(类方法缓存) 方法列表中每个方法结构体中记录着方法的名称,方法实现,以及参数类型,其实selec ...
- 19、AngularJs知识点总结 part-1
1.AngularJs AngularJs是一款JavaScript开源库,由Google维护,用来协助单一页面应用程序: AngularJs的目标是通过MVC模式增强基于浏览器的应用,使开发和测试变 ...
- 【java下午茶系列】java三重奏之封装
java中的封装.继承.多态可谓是踏入这一行业的必经之槛,诸多新人在不明就里的情况下将其各种概念背的是滚瓜烂熟.即便是工作多年之后,也不见得能说出个所以然,或许冥冥之中已经写过无数封装的代码,只是 ...
- eclipse集成python(Pydev插件安装)
1.下载PyDev的压缩包,解压后会有features和plugins两个文件夹,将两个文件夹的内容拷贝到eclipse对应的文件夹中,重新启动eclipse 2.配置python 2.1打开ecli ...
- vue零碎收集
在组件中创建dom: let a=document.querySelector('.test'); let newDom=document.createElement("div") ...
- Python全栈工程师(编码)
ParisGabriel Python 入门基础 补充: 主流3操作大系统 Windows: Winxp Win7 Win8 Win10 Unix: Solaris(SUN) IO ...
- python之路——网络编程
一.楔子 你现在已经学会了写python代码,假如你写了两个python文件a.py和b.py,分别去运行,你就会发现,这两个python的文件分别运行的很好.但是如果这两个程序之间想要传递一个数据, ...
- 孤荷凌寒自学python第三十六天文件内容的迭代操作
孤荷凌寒自学python第三十六天python的文件操作对文件内容的迭代操作 (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) 一.os模块的其它文件操作方法补充 1 os.remove(文件 ...
- [C++] Const详解
/**************************************************************** 初级理解: 1.const是定义常量 ==>const意味着只 ...
- 【现代程序设计】homework-01
HOMEWORK-01 1) 建立 GitHub 账户, 把课上做的 “最大子数组之和” 程序签入 已完成. 2) 在 cnblogs.com 建立自己的博客. 写博客介绍自己的 GitHub 账户. ...