【最大M子段和】dp + 滚动数组

题目描述

给定 n 个数求这 n 个数划分成互不相交的 m 段的最大 m 子段和。

给出一段整数序列 A1,A2,A3,A4,...,Ax,...,An ,其中 1≤x≤n≤1,000,000, -32768≤Sx≤32767。

我们定义一种函数 sum(i,j)=Ai + ... + Aj (1≤i≤j≤n,且Ai~Aj 是连续的数)。

现在,我们得到一个正整数 m(1≤x≤m≤30),你的工作是寻找 m 对 i 与 j。这 m 对 i 和 j 满足以下条件:
  sum(i1,j1)+sum(i2,j2)+sum(i3,j3)+...+sum(im,jm)在这个序列中最大。
注意:任意两区间[ix,jx]和[iy,jy]的交集均为空集。

请你求出:最大的 sum(i1,j1)+sum(i2,j2)+sum(i3,j3)+...+sum(im,jm)是多少?

输入格式

第一行两个整数 n,m 。
第二行由空格隔开的 n 个整数,即 A1~An 。

输出格式

请输出我们定义的:sum(i1,j1)+sum(i2,j2)+sum(i3,j3)+...+sum(im,jm)的最大值,即最大的 m 子段和。

样例数据 1

输入

3 1 
1 2 3

输出

6

样例数据 2

输入

6 2 
-1 4 -2 3 -2 3

输出

8

题目分析

形如“求将x,分成y份的最*值”问题,通常dp都为 f[j][i],表示将前j个元素分成i份的最*值。

这道题也一样:f[j][i]如上所述,对于新加入的元素,有两种决策:

  1. 加到上一次的最后一段。
  2. 独立成段。

  转移方程就为:$f[j][i] = max(f[j - 1][i] + val[i], max_{k = 1}^{j - 1}\{f[j - 1][k]\} + val[i])$  

  稍微计算一下,会发现这样的空间已经报表。接下来就是滚动数组登场了。

  可以发现,转移方程中的j这一维总是从上一次的j-1转移,而i不变,而且f[j - 1][k]也只需要上一次的最大值即可,那么就可以使用滚动数组进行如下优化:

  1. 去掉i这一维, 并把i这一维提到外循环->保证j-1到j都是i这一维。 数组只需要f[N]

  2.用mx[j - 1]来表示$max_{k = 1}^{j - 1}\{f[j - 1][k]\} $, 每次内循环(j)更新, 以供下一个外循环(i)使用。

  于是转移变为:

for(int i = 1; i <= m; i++){
        ll tmp = -oo;
        for(int j = i; j <= n; j++){
            f[j] = max(f[j - 1] + val[j], mx[j - 1] + val[j]);
            tmp = max(tmp, f[j - 1]);
            mx[j - 1] = tmp;
        }
    }

code

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
using namespace std;

const int N = 1e6 + 5, oo = 0x7fffffff;
int n, m;
typedef long long ll;
ll f[N], mx[N], val[N];

inline ll read(){
    ll i = 0, f = 1; char ch = getchar();
    for(; (ch < ‘0‘ || ch > ‘9‘) && ch != ‘-‘; ch = getchar());
    if(ch == ‘-‘) f = -1, ch = getchar();
    for(; ch >= ‘0‘ && ch <= ‘9‘; ch = getchar())
        i = (i << 3) + (i << 1) + (ch - ‘0‘);
    return i * f;
}

inline void wr(ll x){
    if(x < 0) putchar(‘-‘), x = -x;
    if(x > 9) wr(x / 10);
    putchar(x%10+‘0‘);
}

int main(){
    n = read(), m = read();
    for(int i = 1; i <= n; i++) val[i] = read();
    for(int i = 1; i <= m; i++){
        ll tmp = -oo;
        for(int j = i; j <= n; j++){
            f[j] = max(f[j - 1] + val[j], mx[j - 1] + val[j]);
            tmp = max(tmp, f[j - 1]);
            mx[j - 1] = tmp;
        }
    }
    ll ans = -oo;
    for(int i = m; i <= n; i++)
        ans = max(ans, f[i]);
    wr(ans), putchar(‘\n‘);
    return 0;
}
时间: 2024-10-18 23:21:00

【最大M子段和】dp + 滚动数组的相关文章

HDU 1024 Max Sum Plus Plus --- dp+滚动数组

HDU 1024 题目大意:给定m和n以及n个数,求n个数的m个连续子系列的最大值,要求子序列不想交. 解题思路:<1>动态规划,定义状态dp[i][j]表示序列前j个数的i段子序列的值,其中第i个子序列包括a[j], 则max(dp[m][k]),m<=k<=n 即为所求的结果 <2>初始状态: dp[i][0] = 0, dp[0][j] = 0; <3>状态转移: 决策:a[j]自己成为一个子段,还是接在前面一个子段的后面 方程: a[j]直接接在前面

poj3624 01背包入门 dp+滚动数组

poj3624 01背包 dp+滚动数组 Charm Bracelet Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 25458   Accepted: 11455 Description Bessie has gone to the mall's jewelry store and spies a charm bracelet. Of course, she'd like to fill it with the bes

POJ3071-Football(概率DP+滚动数组)

Football Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 2769   Accepted: 1413 Description Consider a single-elimination football tournament involving 2n teams, denoted 1, 2, -, 2n. In each round of the tournament, all teams still in the

HDU 5617 Jam&#39;s maze dp+滚动数组

题目链接: hdu: http://acm.hdu.edu.cn/showproblem.php?pid=5617 bc(中文):http://bestcoder.hdu.edu.cn/contests/contest_chineseproblem.php?cid=666&pid=1003 题解: 设dp[x1][x2][i]表示第i步时,从(1,1)点走到了(x1,y1),(n,n)点走到了(x2,y2)点的合法的总数. 1 #include<iostream> 2 #include

[ACM] HDU 4576 Robot (概率DP,滚动数组)

Robot Problem Description Michael has a telecontrol robot. One day he put the robot on a loop with n cells. The cells are numbered from 1 to n clockwise. At first the robot is in cell 1. Then Michael uses a remote control to send m commands to the ro

HDU - 2294 Pendant (DP滚动数组降维+矩阵快速幂)

Description On Saint Valentine's Day, Alex imagined to present a special pendant to his girl friend made by K kind of pearls. The pendant is actually a string of pearls, and its length is defined as the number of pearls in it. As is known to all, Ale

HDU 5119 Happy Matt Friends (背包DP + 滚动数组)

题目链接:HDU 5119 Problem Description Matt has N friends. They are playing a game together. Each of Matt's friends has a magic number. In the game, Matt selects some (could be zero) of his friends. If the xor (exclusive-or) sum of the selected friends'ma

HDU 3392 Pie(DP+滚动数组)

题意:有一些男生女生,男生女生数量差不超过100 ,男生女生两两配对.要求求出一种配对方法,使每一对的高度差的和最小. 思路:(我是真的笨笨笨!!磨磨唧唧写一堆是因为我笨!我看了别人的博客,思路全是学别人的,轻喷!)设人少的一组人数为n,b[],人多的一组人数为m,g[](b[],g[]先排好序),用dp[i][j]表示n中的前i个人与m中的前j个人配对所得到的最小值. 那么dp[i][j]就是min(dp[i-1][k]+|b[i]-g[k]|),就是n中前i-1个人和m中前1~k个人配对的最

vijos 1907 DP+滚动数组

描述 Flappy Bird 是一款风靡一时的休闲手机游戏.玩家需要不断控制点击手机屏幕的频率来调节小鸟的飞行高度,让小鸟顺利通过画面右方的管道缝隙.如果小鸟一不小心撞到了水管或者掉在地上的话,便宣告失败. 为了简化问题,我们对游戏规则进行了简化和改编: 游戏界面是一个长为 n,高为 m 的二维平面,其中有k 个管道(忽略管道的宽度). 小鸟始终在游戏界面内移动.小鸟从游戏界面最左边 任意整数高度位置出发,到达游戏界面最右边时,游戏完成. 小鸟每个单位时间沿横坐标方向右移的距离为 1,竖直移动的