先上题目
Max Sum Plus Plus Plus
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 1186 Accepted Submission(s): 591
Problem Description
给定一个由n个正整数组成的整数序列
a1 a2 a3 ... an
求按先后次序在其中取m段长度分别为l1、l2、l3...lm的不交叠的连续整数的和的最大值。
a1 a2 a3 ... an
求按先后次序在其中取m段长度分别为l1、l2、l3...lm的不交叠的连续整数的和的最大值。
Input
第一行是一个整数n(0 ≤ n ≤ 1000),n = 0表示输入结束
第二行的第一个数是m(1 ≤ m ≤ 20),
第二行接下来有m个整数l1,l2...lm。
第三行是n个整数a1, a2, a2 ... an.
第二行的第一个数是m(1 ≤ m ≤ 20),
第二行接下来有m个整数l1,l2...lm。
第三行是n个整数a1, a2, a2 ... an.
Output
输出m段整数和的最大值。
Sample Input
3
2 1 1
1 2 3
4
2 1 2
1 2 3 5
0
Sample Output
5
10
中文题意不解释,这题可以像背包问题那样解。
dp[i][j]表示前j个数中分成i段可以得到的最大值。
sum[i]表示前i个数的最大值。
状态转移方程:dp[i][j]=max( dp[i][j-1] , dp[i-1][j-l[i]] + ( sum[j]-sum[j-l[i]] ) )
意思就是如果不选a[j],那么dp[i][j]=dp[i][j-1],如果选a[j],d[i][j]=dp[i-1][j-l[i]]+(sum[j]-sum[j-l[i]])
详细的分析还需要再搞懂一点才可以写。
上代码:
1 #include <cstdio> 2 #include <cstring> 3 #define max(x,y) (x >= y ? x : y) 4 #define MAX 1002 5 #define LL long long 6 using namespace std; 7 8 LL a[MAX],sum[MAX],l[22]; 9 LL dp[22][MAX]; 10 11 int main() 12 { 13 int n,m,st; 14 //freopen("data.txt","r",stdin); 15 while(scanf("%d",&n),n){ 16 scanf("%d",&m); 17 for(int i=1;i<=m;i++) scanf("%I64d",&l[i]); 18 sum[0]=0; 19 for(int i=1;i<=n;i++){ 20 scanf("%I64d",&a[i]); 21 sum[i]=sum[i-1]+a[i]; 22 } 23 memset(dp,0,sizeof(dp)); 24 st=0; 25 for(int i=1;i<=m;i++){ 26 st+=l[i]; 27 for(int j=st;j<=n;j++){ 28 dp[i][j]=max(dp[i][j-1],dp[i-1][j-l[i]]+(sum[j]-sum[j-l[i]])); 29 } 30 } 31 printf("%I64d ",dp[m][n]); 32 } 33 return 0; 34 }