问题描述
C*++语言和C++语言非常相似,然而C*++的程序有时会出现意想不到的结果。比如像这样的算术表达式:
- 表达式=基本式 / 表达式+基本式 / 表达式-基本式
- 基本式=增量 / 系数*增量
- 增量=a++ / ++a
- 系数=0/1/2/……/1000
如“5*a++-3*++a+a++
”是合法的C*++表达式。
计算这样的表达式的值的方法:
- 首先是每个基本式进行计算,然后按照正常的算术运算法则计算。
- 如果一个基本式包含“a++”,则先进行乘法运算再使变量a权值+1;如果一个基本式包含“++a”,则先使变量a权值+1再进行乘法运算。
- 然而基本式可以按任意顺序计算,这就是为什么计算结果是完全无法预料的。你的任务就是去找到最大的可能结果。
输入
第一行,一个整数n,表示变量a的初始值。第二行,一个合法的C*++表达式。
输出
共一行,一个整数ans,表示最大可能结果。
样例输入
input 1:
1
5*a++-3*++a+a++
output 1:
11
input 2:
3
a+++++a
output 2:
8
数据规模和约定
对于20%的数据,表达式长度<=20。另有20%的数据,满足n>=0。对于100%的数据,-1000<=n<=1000,表达式长度<=10000。注意表达式开头可能有负号!
思路
题目的意思就是有很多个 a++ 或 ++a,每个a++之前都有一个系数,a++ 或 ++a 进行的顺序可以随意,求最后表达式最大值
其实题目tag不说是贪心我会往DP上面想的
如果是贪心的话,很容易想到:因为a是逐渐增加的,那么让小的数乘上小的a,让大的数乘上大的a,就可以使值最大
证明 1:优先选择大数乘大a
假设a从 a 变成 a+1,有两个数 x, x+1,那么有两种选择:
- (x * a) + ((x+1) * (a+1)) = 2ax + x + a + 1
- ((x+1) * a) + (x * (a+1)) = 2ax + x + a
显然让 【大的数】 和 【大的a】 相乘比较赚
但是 a++ 和 ++a 的顺序对于结果有没有影响呢?
答案是没有
证明 2: a++ 和 ++a 的顺序对于结果无影响:
-
相同的数字x,a++ 和 ++a 的顺序没有影响
先a++:(x * a) + (x * (a+2)) = 2ax + 2x
先++a:(x * (a+1)) + (x * (a+1)) = 2ax + 2x -
不同的数字x, y,a++ 和 ++a 的顺序没有影响
先a++:r1 = (x * a) + (y * (a+2)) = ax + ay + 2y
先++a:r2 = (x * (a+1)) + (y * (a+1)) = ax + ay + x + y
r1, r2 的大小只和 x,y 的大小有关,x > y,则 r2 > r1,反之
这也再次说明了贪心策略是【大的数】 和 【大的a】 相乘
代码
贪心比较容易实现,复杂度也不会太大
#include <iostream>
#include <string>
using namespace std;
typedef long long ll;
string app = "a++";
string ppa = "++a";
#define MAXLEN 10009
#define char2int(x) ((int)(x - '0'))
// nums[i][0] 存储第i个a++/++a的系数
// nums[i][1]=0表示是a++,nums[i][1]=1表示是++a
int nums[MAXLEN