前言
黑皮书上推的一道题,一直没理解题意,以为划分成m段就是将所有划分成m段而不能有剩余,最后才发现应该是从序列中取出m段然后使其和最大,啊这…找规律吧~
第二次编写,感觉之前理解的还不是很透彻,自己都有疑惑的东西,对读的人也一定有问题,所以返工一波~~~
一、题目
Sample Input:
1 3 1 2 3
2 6 -1 4 -2 3 -2 3
Sample Output:
6
8
二、题目分析解决
1.MLE情况
通过以上分析可以求出递推式:dp[i][j]=max(dp[i][j-1],tmp)+a[j];
tmp=max(圈1中的最大值)【循环时求出就行】
还是贴一波代码吧
(定义二维数组发生MLE)
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
using namespace std;
//算法思想:从n个数中,取出m段,求最大和
//定义一个dp[i][j],表示前j个数选出i组时的最大和
// 两种选择求dp[i][j],无非两种情况,一种自己一组,一种加入到i组中任意一组,
//自己一组:则此时要看前j-1个数对应的i-1个组所有结果的最大值,
// 即选取max(dp[i-1][i-1]...dp[i-1][j-1])最大值
//加入到前i组中任意一组:此时只需加上dp[i][j-1]即可
//代码走一波~
const int maxn=1000005;
int dp[100][maxn];
int a[maxn];
int n,m;
const int inf=0x7ffffff;
void solve() {
int tmp;
tmp=-inf;
for(int i=1; i<=m; ++i) {
for(int j=i; j<=n; ++j) {
dp[i][j]=max(dp[i][j-1],tmp)+a[j];
if(dp[i-1][j-1]>tmp) tmp=dp[i-1][j-1];//定义一个tmp存最大
}
}
}
int main() {
while(cin>>m>>n) {
memset(a,0,sizeof(a));
for(int i=1; i<=n; i++) {
cin>>a[i];
}
memset(dp,0,sizeof(dp));
solve();
cout<<dp[m][n]<<endl;
}
}
2.AC代码–滚动数组
想了一晚上,终于想明白了
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
using namespace std;
const int maxn=1000005;
int a[maxn];
int n,m;
const int inf=0x7ffffff;
int dp[maxn];
int premax[maxn];
void solve(){
int tmp;
tmp=-inf;
for(int i=1;i<=m;++i){
tmp=-inf;
for(int j=i;j<=n;++j){
// dp[i][j]=max(dp[i][j-1],tmp)+a[j];
dp[j]=max(dp[j-1],premax[j-1])+a[j];// premax[j-1]表示上一层前j-1的最大和
premax[j-1]=tmp;//更新premax数组,每次都等到dp[j]用完了premax[j-1]才更新
//因为这么做才是之前即i-1层的premax[j-1];
tmp=max(tmp,dp[j]);
//新更新的premax[j-1]求法:
//premax数组存的是上一层(i-1)的前j-1项最大dp值;
//这里的更新是在本层dp用完premax数组后更新,
//所以更新的值就是此时前j项的最大dp值
}
}
cout<<tmp<<endl;
}
int main(){
while(cin>>m>>n){
memset(a,0,sizeof(a));
memset(premax,0,sizeof(premax));
for(int i=1;i<=n;i++){
cin>>a[i];
}
memset(dp,0,sizeof(dp));
solve();
}
}
三、THE END
滑动数组还是要花很长时间去理解,就像premax的使用一样,一维数组的更新是在什么时候,如何利用语句间的顺序来表示使用的顺序以来保证更新的顺序,感觉这一晚上没白用,还是会了90%以上,超级欢迎对这道题有疑问的你来评论,最近都在刷题,每刷一道写一篇博客用来巩固,所以经常在线
明天加油,今天晚安