题目如下:
题目链接
Max Sum Plus Plus
题解 or 思路:
经典的动态规划问题
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j], 前
j
j
j 个物品, 我们分成题目要求的
i
i
i 组
对于第
j
j
j 个物品, 我们可以将它分到 第
k
k
k 组中, 或者分到新的一组中。
d
p
[
i
]
[
j
]
=
m
a
x
(
d
p
[
i
−
1
]
[
j
−
1
]
,
d
p
[
k
]
[
j
−
1
]
)
,
k
≥
j
−
1
,
k
<
i
dp[i][j] = max(dp[i-1][j-1], dp[k][j-1]), k \ge j - 1 , k < i
dp[i][j]=max(dp[i−1][j−1],dp[k][j−1]),k≥j−1,k<i
我们会发现 空间太大了,接下来是空间优化:
对于
m
a
x
{
d
p
[
k
]
[
j
−
1
]
}
,
k
≥
j
−
1
,
k
<
i
max\{dp[k][j - 1]\}, k \ge j - 1 , k < i
max{dp[k][j−1]},k≥j−1,k<i 我们可以滚动数组优化一下,把这个 记录成
p
r
e
[
j
−
1
]
pre[j - 1]
pre[j−1]
d
p
[
i
]
[
j
]
=
m
a
x
(
d
p
[
i
]
[
j
−
1
]
,
p
r
e
[
j
−
1
]
)
+
s
[
j
]
dp[i][j] = max(dp[i][j - 1], pre[j - 1]) + s[j]
dp[i][j]=max(dp[i][j−1],pre[j−1])+s[j]
我们发现转移
i
i
i 这一维可以去掉了
d
p
[
j
]
=
m
a
x
(
d
p
[
j
−
1
]
,
p
r
e
[
j
−
1
]
)
+
s
[
j
]
dp[j] = max(dp[j - 1], pre[j - 1]) + s[j]
dp[j]=max(dp[j−1],pre[j−1])+s[j]
AC 代码如下:
const int N = 1000009;
int n, m;
int dp[N], pre[N], s[N];
void solve()
{
for (int i = 1; i <= n; i++)
scanf("%d", &s[i]), dp[i] = pre[i] = 0;
int tt;
for (int i = 1; i <= m; i++)
{
tt = -inf;
for (int j = i; j <= n; j++)
{
dp[j] = max(dp[j - 1], pre[j - 1]) + s[j];
pre[j - 1] = tt;
tt = max(tt, dp[j]);
}
}
cout << tt << '\n';
}
int main()
{
while (~scanf("%d %d", &m, &n))
solve();
}