看别人题解写出来的,指路:https://blog.51cto.com/13688928/2117013
题目意思:在一个数列里找m个字段,使得他们的和最大。
dp[i][j]来表示在前j个数中,以下标j结尾并分为i段的最大和。
动态转移方程:dp[i][j]=max(dp[i][j-1]+a[j],max(dp[i-1][k]) + a[j] ) (0<k<j)
下面解释k的意义:
max( dp[i-1][k] ) + a[j] )表示的前k个数分成i-1组时的最大值。
所以也要对k进行遍历来求解max(dp[i-1][k]),但这样显然会超时。所以可以用一个pre【】数组来记录前j个分为i组的最大值。
#include <iostream> #include<stdio.h> #include <cstring> #include <algorithm> #include <string.h> #include <queue> //#include <bits/stdc++.h> #define pb push_back #define qc std::ios::sync_with_stdio(0); using namespace std; const int max_n=1000005; typedef long long ll; typedef unsigned long long int ul; typedef double dl; int a[max_n],pre[max_n]; int dp[max_n]; int main() { int n,m,maxn; while(~scanf("%d %d",&m,&n)) { for(int i=1;i<=n;i++) scanf("%d",&a[i]); memset(dp,0,sizeof(dp)); memset(pre,0,sizeof(pre)); for(int i=1;i<=m;i++) { maxn=-1000000; for(int j=i;j<=n;j++) { dp[j]=max(pre[j-1],dp[j-1])+a[j]; pre[j-1]=maxn; maxn=max(maxn,dp[j]); } } printf("%d\n",maxn); } }