[kuangbin带我飞]专题12——基础DP1(1/19)

谁能告诉我怎么删除这个呀

1、

Max Sum Plus Plus

 HDU - 1024

Now I think you have got an AC in Ignatius.L's "Max Sum" problem. To be a brave ACMer, we always challenge ourselves to more difficult problems. Now you are faced with a more difficult problem.

Given a consecutive number sequence S  1, S  2, S  3, S  4 ... S  x, ... S  n (1 ≤ x ≤ n ≤ 1,000,000, -32768 ≤ S  x ≤ 32767). We define a function sum(i, j) = S  i + ... + S  j (1 ≤ i ≤ j ≤ n).

Now given an integer m (m > 0), your task is to find m pairs of i and j which make sum(i  1, j  1) + sum(i  2, j  2) + sum(i  3, j  3) + ... + sum(i  m, j  m) maximal (i  x ≤ i  y ≤ j  x or i  x ≤ j  y ≤ j  x is not allowed).

But I`m lazy, I don't want to write a special-judge module, so you don't have to output m pairs of i and j, just output the maximal summation of sum(i  x, j  x)(1 ≤ x ≤ m) instead. ^_^

InputEach test case will begin with two integers m and n, followed by n integers S 1, S 2, S 3 ... S n.
Process to the end of file.
OutputOutput the maximal summation described above in one line.
Sample Input

1 3 1 2 3
2 6 -1 4 -2 3 -2 3

Sample Output

6
8

 题目大意:给出n个数,求出m段不重复连续子串和的最大值。

(看完题目后并没有思路,于是查了博客=。=)

 思路:

  状态:dp[i][j]表示分成j块并以i为结尾的子段和最大值,mx[i][j]表示dp[0...i][0...j]的最大值。

  划分策略:以a[i]单独为一组作为第j组,或a[i]作为前面组的一部分。

  状态转移方程:如下。

 1 //dp[i][j]意思为分成j块以a[i]结尾的和最大值,mx[i][j]存储着dp[j~i][j]中的最大值。
 2 //划分策略为以a[i]单独为一组作为第j组,或a[i]作为前面组的一部分,所以状态转移方程为
 3 //dp[i][j] = max(dp[i-1][j], mx[i-1][j-1]) + a[i]
 4 //mx[i][j] = max(dp[i][j], mx[i-1][j])
 5 //        for (int j=1;j<=m;j++)
 6 //        {
 7 //            for (int i=j;i<=n;i++)
 8 //            {
 9 //                if (i == j) dp[i][j] = dp[i-1][j-1] + a[i];
10 //                else dp[i][j] = max(dp[i-1][j] + a[i], mx[i-1][j-1] + a[i]);
11 //                mx[i][j] = max(mx[i-1][j], dp[i][j]);
12 //            }
13 //        }
14 //        for (int i=m;i<=n;i++)
15 //            ans = max(ans, dp[i][m]);

  空间压缩:但是题目范围不允许使用我们使用二维数组了,更何况两个,但是这里因为转移方程中调用的都是j-1或是i-1,所以我们可以压缩空间。dp[i] = max(dp[i-1], mx[i-1]) + a[i]中,i == j时,dp[i-1]存放的值为dp[i-1][j-1],mx[i-1]为mx[i-1][j-1];i != j时,dp[i-1]为dp[i-1][j], mx[i-1]为mx[i-1][j-1]。为了满足这个式子,dp数组只需照常填入即可,mx数组必须保证比dp数组慢一步,因为在填入dp[i]时必须保证mx[i-1]还未更新过,还没有从mx[i-1][j-1]变成mx[i-1][j]。

  代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 const int M = 1e6+10;
 6 int dp[M], mx[M];
 7 int a[M], n, m;
 8 int main()
 9 {
10     while (~scanf("%d%d", &m, &n))
11     {
12         memset(dp, 0, sizeof(dp));
13         memset(mx, 0, sizeof(mx));
14         for (int i=1; i<=n; i++)
15             scanf("%d", &a[i]);
16         int q;
17         for (int j=1; j<=m; j++)
18         {
19             q = INT_MIN;
20             for (int i=j; i<=n; i++)
21             {
22                 dp[i] = max(dp[i-1], mx[i-1]) + a[i];
23                 mx[i-1] = q;
24                 q = max(q, dp[i]);
25             }
26         }
27         printf("%d\n", q);
28     }
29 }
View Code

总结:这个状态表示很巧妙。挺神奇的,这个状态是我以前没有写到过的。我目前对于dp的理解还很肤浅,解题思路都是从类似的题目偷过来的,而类似的题目最早是看答案的,意味着我不能独立思考dp问题,不过这一题让我对空间压缩有了一些自己的理解。继续努力吧,希望把这19题全部写完能对dp有自己的理解。

2、

Ignatius and the Princess IV

 HDU - 1029 

猜你喜欢

转载自www.cnblogs.com/FantaDevourer/p/12710027.html
今日推荐