一個長度為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 }
-