题意:求一个序列中的最大 m 段和,m 段不能交叉。

dp[i][0/1][j] 表示已经取完第 i 个物品,第 i 个物品取或不取,取到第 j 个子段。

用vis[i][0/1][j] 表示该 dp 值是否存在。

然后当 vis[i][0][j] 存在,即第 i 个物品不取,之前已经取了 j 个子段,可推得:

  第 i+1 个不取: dp[i+1][0][j]=max(dp[i+1][0][j],dp[i][0][j]);

  第 i+1 个取: dp[i+1][1][j+1]=max(dp[i+1][1][j+1],dp[i][0][j]+a[i]);

当 vis[i][1][j] 存在,即第 i 个物品取,之前已经取了 j 个子段(第 j 段可能还没有取完),可推得:

  第 i+1 个不取: dp[i+1][0][j]=max(dp[i+1][0][j],dp[i][1][j]);

  第 i+1 个取且放在第 j 个子段中: dp[i+1][1][j]=max(dp[i+1][1][j],dp[i][1][j]+a[i]);

  第 i+1 个取且放在第 j+1 个子段中: dp[i+1][1][j+1]=max(dp[i+1][1][j+1],dp[i][1][j]+a[i]);

然后初始化 dp[1][1][1]=a[1],dp[1][0][0]=0;

由于直接开 n*2*m 会MLE,所以将第一维滚动,2*2*m 就完全没有问题,复杂度 O(n*m);

 #include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std; typedef long long ll;
const int maxn=1e6+; int a[maxn];
int dp[][][];
bool vis[][][]; int main(){
int m,n;
while(scanf("%d%d",&m,&n)!=EOF){
for(int i=;i<=n;++i)scanf("%d",&a[i]);
memset(dp,,sizeof(dp));
memset(vis,,sizeof(vis));
dp[][][]=a[];
vis[][][]=;
dp[][][]=;
vis[][][]=;
for(int k=;k<n;++k){
int i=k&;
memset(vis[i^],,sizeof(vis[i^]));
for(int j=;j<=m;++j){
if(vis[i][][j]){
if(!vis[i^][][j]){
vis[i^][][j]=;
dp[i^][][j]=dp[i][][j];
}
else if(dp[i][][j]>dp[i^][][j])dp[i^][][j]=dp[i][][j];
if(!vis[i^][][j+]){
vis[i^][][j+]=;
dp[i^][][j+]=dp[i][][j]+a[k+];
}
else if(dp[i][][j]+a[k+]>dp[i^][][j+])dp[i^][][j+]=dp[i][][j]+a[k+];
}
if(vis[i][][j]){
if(!vis[i^][][j]){
vis[i^][][j]=;
dp[i^][][j]=dp[i][][j];
}
else if(dp[i][][j]>dp[i^][][j])dp[i^][][j]=dp[i][][j];
if(!vis[i^][][j]){
vis[i^][][j]=;
dp[i^][][j]=dp[i][][j]+a[k+];
}
else if(dp[i][][j]+a[k+]>dp[i^][][j])dp[i^][][j]=dp[i][][j]+a[k+];
if(!vis[i^][][j+]){
vis[i^][][j+]=;
dp[i^][][j+]=dp[i][][j]+a[k+];
}
else if(vis[i^][][j+]&&dp[i][][j]+a[k+]>dp[i^][][j+])dp[i^][][j+]=dp[i][][j]+a[k+];
}
}
}
int ans=-0x3f3f3f3f;
if(vis[n&][][m])ans=max(ans,dp[n&][][m]);
if(vis[n&][][m])ans=max(ans,dp[n&][][m]);
printf("%d\n",ans);
}
return ;
}

hdu1024 dp的更多相关文章

  1. HDU1024 DP的优化 最大M子段和问题

    Max Sum Plus Plus Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others ...

  2. hdu1024线性dp

    /* dp[i][j]表示取第i个数时分成了j块 要么是将第i个数加入j块中的最后一块,要么是自成一块,加上前面j-1块的和 状态转移方程: dp[i][j]=max(dp[i-1][j]+a[i], ...

  3. HDU1024(DP)

    Max Sum Plus Plus Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others ...

  4. HDU1024 Max Sum Plus Plus 【DP】

    Max Sum Plus Plus Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others ...

  5. hdu1024 Max Sum Plus Plus 滚动dp

    Max Sum Plus Plus Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others ...

  6. HDU1024 多段最大和 DP

    题目大意: 在n个数,求不重复的m段中的数据总和的最大值 令dp[i][j]表示将前j个数分成 i 段时得到的最大值(必取到第 j 个数) 状态转移可列为 dp[i][j]=Max(dp[i][j-1 ...

  7. HDU1024 Max Sum Plus Plus(dp)

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=1024 #include<iostream> #include<vector> #i ...

  8. HDU1024 Max Sum Plus Plus (优化线性dp)

    Now I think you have got an AC in Ignatius.L's "Max Sum" problem. To be a brave ACMer, we ...

  9. 【hdu1024】简单dp

    http://acm.hdu.edu.cn/showproblem.php?pid=1024 最大m字段和,题目就不多说了,经典dp 这题坑爹...首先不说明m的范围(n<=1000000),还 ...

随机推荐

  1. 更改mysql中当前auto_increment的值的方法

    最近给自己网站更改mysql中当前auto_increment的值 如果在mysql中一个表test中的ID字段设为auto_increment插入两条记录后ID=2,这时删除1条记录,再插入一条变成 ...

  2. SQL Server 2005中的CTE递归查询得到一棵树

    感觉这个CTE递归查询蛮好用的,先举个例子: use City; go create table Tree ( ID int identity(1,1) primary key not null, N ...

  3. A Brief Review of Supervised Learning

    There are a number of algorithms that are typically used for system identification, adaptive control ...

  4. Monkey基本使用流程及测试报告分析

    前一篇文章介绍了Monkey的API函数内容,这篇文章介绍windows环境下Monkey的基本使用方法. 由于博客园年底才能完成对markdown解析的升级,可移步我的个人博客查看此文,已获得更好的 ...

  5. AFNetworking之缓存篇

    苦苦看了我两天,最近后台为了减轻压力,要我做缓存,我说好吧...... 借鉴了别人的说法找到一张图可以看明白好多:       这个是我比较战成一种方案. 好了直接上代码了 首先我们要有自己缓存的类 ...

  6. Mac下手动安装Chromedriver.exe

    Mac OS X Yosemite 10.10.4下,ChromeDriver运行异常,需要手动安装chromedriver.exe Step 1: 打开https://sites.google.co ...

  7. 按月统计tcode和report使用次数的工具

    执行report,输入要查询的日期和user, 工具会按照使用次数从高到低列出输入日期所在的月份内所有该user 曾经使用过的tcode 和report list: REPORT zusertcode ...

  8. 【C】制作简单的时钟减法程序

    #include <stdio.h> #include <stdlib.h> #include <string.h> #define ARGC_NUM 3 #def ...

  9. ARM9的中断控制器

    简要复习一下ARM9中断控制器的控制过程: 1.首先能识别触发的中断(对应中断源必须打开,然后查询当前中断状态寄存器),硬件会操控PC跳到中断向量入口(IRQ_HANDLE,硬件控制的只要是IRQ中断 ...

  10. spring 包下载地址

    留着,以备不时之需: http://repo.spring.io/libs-release-local/org/springframework/spring/