srm 654 div2 1000 (DP,最大连续和拓展, 有亮点)
2015-03-26 23:13
525 查看
题意:
有 a1 - a2 - … - an 这样的式子,最多加两个括号,使得和最大。
比如 1-3-3-4-5
变成 1-(3-3-4-5) = 10
思路:
1)加一个括号
把括号打开得到
a1−a2−...−ai+ai+1+...+aj−aj+1−...−ana_1 - a_2 - ...-a_i + a_{i+1} +...+ a_j - a_{j+1} - ... -a_n
就是求最大连续和
2)加两个括号 (两个括号嵌套和分开)
同理,我们把括号打开可以得到两段求和
于是,任务变成了从 a3...ana_3...a_n求两段或一段最大连续和
PS:
看到一种非常简洁的做法, 非常值得思考!!
有 a1 - a2 - … - an 这样的式子,最多加两个括号,使得和最大。
比如 1-3-3-4-5
变成 1-(3-3-4-5) = 10
思路:
1)加一个括号
把括号打开得到
a1−a2−...−ai+ai+1+...+aj−aj+1−...−ana_1 - a_2 - ...-a_i + a_{i+1} +...+ a_j - a_{j+1} - ... -a_n
就是求最大连续和
2)加两个括号 (两个括号嵌套和分开)
同理,我们把括号打开可以得到两段求和
于是,任务变成了从 a3...ana_3...a_n求两段或一段最大连续和
PS:
看到一种非常简洁的做法, 非常值得思考!!
// dp[0]...dp[4] 分别代表从没有括号到有两个括号, // 且最后是连续的减号这5种情况 int dp[5], tmp[5]; for (int i=2;i<n;++i) { tmp[0] = dp[0] - a[i]; tmp[1] = max (dp[0], dp[1]) + a[i]; tmp[2] = max (dp[1], dp[2]) + a[i]; tmp[3] = max (dp[2], dp[3]) + a[i]; tmp[4] = max (dp[3], dp[4]) + a[i]; for (int j=0;j<5;++j) dp[j] = tmp[j]; } int mx = -inf;for (int i=0;i<5;++i) mx = max (mx, dp[i]); int ans = mx + a[0] - a[1];
const int Maxn = 2000; int dp[2][Maxn+5], L[Maxn+5], R[Maxn+5]; class SuccessiveSubtraction2 { public: int go (vector<int> &a) { int n = a.size(); vector<int> pre(n+5); pre[1] = a[0];rep(i, 2, n) pre[i] = pre[i-1] - a[i-1]; if (n < 3) return pre ; dp[0][3] = a[2]; rep(i, 4, n) dp[0][i] = max (dp[0][i-1]+a[i-1], a[i-1]); dp[1] = a[n-1]; urep(i, n-1, 3) dp[1][i] = max (dp[1][i+1]+a[i-1], a[i-1]); L[2] = 0;rep(i, 3, n) L[i] = max (L[i-1], dp[0][i]); // 当连续和为负的时候,变号没有意义 // 用0来代替它,表示不取 R[n+1] = 0;urep(i, n, 3) R[i] = max (R[i+1], dp[1][i]); int mx = max (0, max (R[3], L )); rep(i, 3, n-1) mx = max (mx, max (L[i], 0) + max (R[i+1], 0)); return pre + mx*2; } vector <int> calc(vector <int> a, vector <int> p, vector <int> v) { vector<int> ans; for (int i=0;i<p.size();++i) { a[p[i]] = v[i]; ans.push_back(go(a)); } return ans; } };
相关文章推荐
- topcoder SRM 654 DIV2 1000 SuccessiveSubtraction2 题解(dp)
- srm 308 div2 1000(DP, 离散背包+连续背包)
- 树中走N步求获得的最大金币数 树形DP SRM 666 div2 problem999
- TopCoder SRM 663 Div2 Problem 1000 - CheeseRolling (状压dp)
- poj 2479 Maximum sum(简单dp,最大连续和拓展)
- srm 655 div2 1000(DP进阶,枚举状态)
- srm 653 div2 1000(dp)
- srm 302 div2 1000(简单题,bfs,dp)
- srm 304 div2 1000(环形DP进阶,几何)
- Topcoder SRM 636 Div2 1000(切蛋糕,最后一块给自己。最小值中求最大值,二分+枚举)
- srm 181 div1 1000(状压dp)
- srm 301 div2 1000 (经典dp, 括号匹配)
- TopCoder SRM 648 Div2 Problem 1000 - ABC (DP)
- srm 306 div2 1000 (字符串dp,进阶)
- Topcoder SRM 635 Div2 1000 (一种 O(n) 求一棵树中最长连续边 长度的方法)
- TopCoder SRM 672 Div2 Problem 1000 - Tdetectived2 (状压dp)
- SRM 511 DIV1 500pt(DP)
- SRM 514 DIV1 500pt(DP)
- TopCoder SRM 666 Div2 Problem 999 - WalkOverATreeDiv2 (树形DP)
- DP SRM 661 Div2 Hard: ColorfulLineGraphsDiv2