给出n个数 让你找到一个子序列 a j 1 − a j 2 + a j 3 − a j 4 + a j 5 . . . . . . a_{j1}-a_{j2}+a_{j3}-a_{j4}+a_{j5}... ... aj1−aj2+aj3−aj4+aj5......和最大。
其实很快就想到过dp[i][2]记录前i个数两种状态结尾的最大值,不过没细想下去。
dp[i][1]表示前i个数以减号结尾的最大值,dp[i][0]表示前i个数以加号结尾的最大值
先处理出dp[i][0]为前i个数的最大值(也就是只选最大值以加号结尾)
然后有四种状态转移:
d
p
[
i
]
[
0
]
=
m
a
x
(
d
p
[
i
]
[
0
]
,
d
p
[
i
−
1
]
[
0
]
)
dp[i][0]=max(dp[i][0],dp[i-1][0])
dp[i][0]=max(dp[i][0],dp[i−1][0])
d
p
[
i
]
[
0
]
=
m
a
x
(
d
p
[
i
]
[
0
]
,
d
p
[
i
−
1
]
[
1
]
+
a
[
i
]
)
dp[i][0]=max(dp[i][0],dp[i-1][1]+a[i])
dp[i][0]=max(dp[i][0],dp[i−1][1]+a[i])
d
p
[
i
]
[
1
]
=
m
a
x
(
d
p
[
i
−
1
]
[
1
]
,
d
p
[
i
]
[
1
]
)
dp[i][1]=max(dp[i-1][1],dp[i][1])
dp[i][1]=max(dp[i−1][1],dp[i][1])
d
p
[
i
]
[
1
]
=
m
a
x
(
d
p
[
i
−
1
]
[
1
]
,
d
p
[
i
−
1
]
[
0
]
−
a
[
i
]
)
dp[i][1]=max(dp[i-1][1],dp[i-1][0]-a[i])
dp[i][1]=max(dp[i−1][1],dp[i−1][0]−a[i])
其中,因为dp[i][1]全为0,因此第三种可以省略。
long long a[300010];
long long dp[300010][2]; //dp[i][1]表示前i个数以减号结尾的最大值,dp[i][0]表示前i个数以加号结尾的最大值
int main()
{
long long t;
scanf("%lld", &t);
while (t--)
{
fill(dp[0], dp[0] + 300010 * 2, 0);
long long n, q;
scanf("%lld%lld", &n, &q);
for (long long i = 1; i <= n; i++)
{
scanf("%lld", &a[i]);
dp[i][0] = max(dp[i - 1][0], a[i]);
}
for (long long i = 1; i <= n; i++)
{
dp[i][0] = max(dp[i - 1][1] + a[i], max(dp[i - 1][0], dp[i][0]));
dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] - a[i]);
}
printf("%lld\n", dp[n][0]);
}
return 0;
}
该博客探讨了一种动态规划方法,用于解决寻找序列中子序列交替求和的最大值问题。通过维护两个状态dp[i][0](以加号结尾的最大值)和dp[i][1](以减号结尾的最大值),博主详细阐述了状态转移方程,并给出了简洁的C++代码实现。算法关键在于考虑前i个数以加号或减号结尾时的最大和,并通过迭代更新状态来找到最优解。
1239

被折叠的 条评论
为什么被折叠?



