AtCoder Regular Contest 066 E - Addition and Subtraction Hard (结论+DP)
Time limit : 2sec / Memory limit : 256MB
Score : 900 points
Problem Statement
Joisino has a formula consisting of N terms: A1 op1 A2 … opN−1 AN. Here, Ai is an integer, and opi is an binary operator either +
or -
. Because Joisino loves large numbers, she wants to maximize the evaluated value of the formula by inserting an arbitrary number of pairs of parentheses (possibly zero) into the formula. Opening parentheses can only be inserted immediately before an integer, and closing parentheses can only be inserted immediately after an integer. It is allowed to insert any number of parentheses at a position. Your task is to write a program to find the maximum possible evaluated value of the formula after inserting an arbitrary number of pairs of parentheses.
Constraints
- 1≦N≦105
- 1≦Ai≦109
- opi is either
+
or-
.
Input
The input is given from Standard Input in the following format:
N A1 op1 A2 … opN−1 AN
Output
Print the maximum possible evaluated value of the formula after inserting an arbitrary number of pairs of parentheses.
Sample Input 1
3 5 - 1 - 3
Sample Output 1
7
The maximum possible value is: 5−(1−3)=7.
Sample Input 2
5 1 - 2 + 3 - 4 + 5
Sample Output 2
5
The maximum possible value is: 1−(2+3−4)+5=5.
Sample Input 3
5 1 - 20 - 13 + 14 - 5
Sample Output 3
13
The maximum possible value is: 1−(20−(13+14)−5)=13.
题意:
给你一个只含有数字和加减号的字符串表达式,你可以加无数个括号,来改变运算顺序。
让你求出这个表达式能表达的最大的结果值。
思路:
首先我们要知道这个结论,
即一个表达式最多有效 括号最多是两层,因为只有在负号后面加括号才有作用,那么一个括号对括号里面的数值的影响是取负号一次,两层是取一部分是负,一部分是正(两层里的),如果有三层,那么第三层提取到最外边一层不会改变数值。
那么我们即可定义dp的状态
dp[i][j] 表示到第i个数时,第i个数后面有j个括号时,表示式的最大值。
那么我们来分析一下转移:
我们从i-1转移到i
当是‘+’时
我们可以在 dp[i-1][j] 后面直接加上 a[i] 即可转移到 dp[i][0]
在d[i-1][1] 括号里 加入a[i] ,贡献值为 - a[i] ,可以转移到dp[i][1]
dp[i-1][2] 最里层括号加入a[i] ,贡献值 为+ a[i] 可以转移到dp[i][2]
当是'-' 时
我们默认减号后面必须加括号,即使只包括自己 即这样的 - ( a[i] )
那么我们把负号后面的dp[i][0] = -inf ,即无穷小,不影响我们其他的运算。
我们可以在 dp[i-1][0/1 ]后面加上 -(a[i]) 即转移到 dp[i-1][1]
在dp[i-1][1]的括号里面加上 - (a[i] ),或者dp[i-1][2] 的外层括号里加上 - (a[i])
转移到dp[i][2] ,数值贡献时 +a[i]
这样就把全部的转移表示出来了,注意开ll。
细节见代码:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <queue> #include <stack> #include <map> #include <set> #include <vector> #include <iomanip> #define ALL(x) (x).begin(), (x).end() #define rt return #define dll(x) scanf("%I64d",&x) #define xll(x) printf("%I64d\n",x) #define sz(a) int(a.size()) #define all(a) a.begin(), a.end() #define rep(i,x,n) for(int i=x;i<n;i++) #define repd(i,x,n) for(int i=x;i<=n;i++) #define pii pair<int,int> #define pll pair<long long ,long long> #define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0) #define MS0(X) memset((X), 0, sizeof((X))) #define MSC0(X) memset((X), '\0', sizeof((X))) #define pb push_back #define mp make_pair #define fi first #define se second #define eps 1e-6 #define gg(x) getInt(&x) #define db(x) cout<<"== [ "<<x<<" ] =="<<endl; using namespace std; typedef long long ll; ll gcd(ll a,ll b){return b?gcd(b,a%b):a;} ll lcm(ll a,ll b){return a/gcd(a,b)*b;} ll powmod(ll a,ll b,ll MOD){ll ans=1;while(b){if(b%2)ans=ans*a%MOD;a=a*a%MOD;b/=2;}return ans;} inline void getInt(int* p); const int maxn=1000010; // const int inf=0x3f3f3f3f; /*** TEMPLATE CODE * * STARTS HERE ***/ int n; char op[maxn]; int a[maxn]; ll dp[maxn/10][4]; const ll inf=(ll)(1e18); int main() { //freopen("D:\\common_text\\code_stream\\in.txt","r",stdin); //freopen("D:\\common_text\\code_stream\\out.txt","w",stdout); gbtb; cin>>n; cin>>a[1]; repd(i,2,n) { cin>>op[i]>>a[i]; } dp[1][0]=a[1]; dp[1][1]=dp[1][2]=-inf; repd(i,2,n) { if(op[i]=='+') { dp[i][0]=max(dp[i-1][0],max(dp[i-1][2],dp[i-1][1]))+a[i]; dp[i][1]=dp[i-1][1]-a[i]; dp[i][2]=dp[i-1][2]+a[i]; }else { dp[i][0]=-inf; dp[i][1]=max(dp[i-1][0],dp[i-1][1])-a[i]; dp[i][2]=max(dp[i-1][2],dp[i-1][1])+a[i]; } } cout<<max(dp[n][0],max(dp[n][1],dp[n][2]))<<endl; return 0; } inline void getInt(int* p) { char ch; do { ch = getchar(); } while (ch == ' ' || ch == '\n'); if (ch == '-') { *p = -(getchar() - '0'); while ((ch = getchar()) >= '0' && ch <= '9') { *p = *p * 10 - ch + '0'; } } else { *p = ch - '0'; while ((ch = getchar()) >= '0' && ch <= '9') { *p = *p * 10 + ch - '0'; } } }