题目地址:https://vjudge.net/contest/295210#problem
参考博客:https://blog.youkuaiyun.com/codeswarrior/article/details/80310401
题目大意:输入m,n,和a[i](1<=i<=n),在a数组中找m个不重叠的区间,且区间和最大。
方法:dp.
用dp[i][j]来存前j个数分成i个区间的后所有区间和,所以会出现两种情况:a[j]+dp[i][j-1] (即a[j]不新开一个区间,而存入前一个区间中去),或者a[j]自己新开一个区间a[i]+dp[i-1][k](即将a[j]存入);状态转移方程:
但是,这个方法会出现两个问题:查询超时,数组太大。
在原来的基础下进行改进。dp开成一维数组,再开一个Max数组(Max[i][j]表示前j个数将会分成i(可能是分成i-1或者i-2或者....i-i+1)个区间后的最大区间和,但是这里开二维的话还是会出现超时和数组太大的问题,所以这里也用一维数组,具体操作方法,请看代码)。既然知道了解决方法那么给出新的状态转移方程:
如果这题用c++写的话,用int来表示就行了,如果非要用long long ,最好加个ios::sync_with_stdio(false);
code:
/*
https://vjudge.net/contest/295210#problem/A
*/
#include<iostream>
#include<string.h>
using namespace std;
typedef long long ll;
const int inf=0x7fffffff;
const int maxn=1000005;
int dp[maxn],Max[maxn],a[maxn];
int main(){
// ios::sync_with_stdio(false);
int n,m;
int i,j;
int ma;
while(cin>>m>>n){
for(i=1;i<=n;i++) cin>>a[i];
memset(dp,0,sizeof dp);
memset(Max,0,sizeof Max);
for(i=1;i<=m;i++){
ma=-inf;
for(j=i;j<=n;j++){//分成i个区间,至少需要i个数。
dp[j]=max(dp[j-1]+a[j],Max[j-1]+a[j]);
Max[j-1]=ma;
ma=max(ma,dp[j]);
}
}
cout<<ma<<endl;
}
return 0;
}
注意初始化!!!