数组分组(DP)

 

一个长度为n的数组a,我们可以把它分成任意组,每一组是一段连续的区间。

比如数组1,2,3,4,5可以分成(1,2),(3,4,5)两个组。每个分组都有一个权值,这个权值就是分组里面每个数的乘积对1000取模的结果。对于数组a的一个分组方案,总权值就是每个分组的权值和。

那么对于数组a,分组以后最大的权值和是多少?

输入格式

输入第一行一个整数n(1≤n≤1000)。

接下来一行n个整数,表示数组a,数组中每个元素都小于等于100。

输出格式

数组最大的分组权值和。

样例输入

7
52 26 1 36 72 48 43

样例输出

1596

 

 

我们用dp[i]表示前i个数分组的最大权值,对于位置i,我们可以枚举最后一个分组的起始位置为j,计算i,j之间的权值,然后更新dp[i]即可。

为了避免过多的计算,我们需要预处理出来每个区间的乘积对1000取模的结果。

 

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <iostream>
 4 #include <string>
 5 #include <math.h>
 6 #include <algorithm>
 7 #include <vector>
 8 #include <stack>
 9 #include <queue>
10 #include <set>
11 #include <map>
12 #include <sstream>
13 const int INF=0x3f3f3f3f;
14 typedef long long LL;
15 const int mod=1e9+7;
16 const double PI = acos(-1);
17 const double eps =1e-8;
18 #define Bug cout<<"---------------------"<<endl
19 const int maxn=1e5+10;
20 using namespace std;
21 
22 int a[1010];
23 int sum[1010][1010];//sum[i][j]表示区间i~j的乘积对1000的模 
24 int dp[1010];
25 
26 int main()
27 {
28     int n;
29     scanf("%d",&n);
30     for(int i=1;i<=n;i++)
31         scanf("%d",&a[i]);
32     for(int i=1;i<=n;i++)//预处理 
33     {
34         sum[i][i]=a[i];
35         for(int j=i+1;j<=n;j++)
36             sum[i][j]=sum[i][j-1]*a[j]%1000;
37     }
38     dp[1]=a[1];
39     for(int i=2;i<=n;i++)//求dp[i] 
40     {
41         for(int j=1;j<i;j++)//向前遍历j,更新dp[i] 
42             dp[i]=max(dp[i],dp[j]+sum[j+1][i]);
43     }
44     printf("%d\n",dp[n]);
45     return 0;
46 }

 

 

 

 

 

-

posted @ 2020-01-16 14:08  jiamian22  阅读(1898)  评论(0编辑  收藏  举报