UESTC 876 爱管闲事 --DP
题意:即求给定n个数字(a1,a2,……an),不改变序列,分成M份,使每一份和的乘积最大。
思路:dp[i][j]表示把前i个数字,分成j份所能得到的最大乘积。
转移方程:dp[i][j] = max{ dp[k][i-1]*sum(k+1,j) } 其中显然j<=i(分成j份,至少要有i个数才能分)且i-1<=k<j
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; #define N 10007 int a[22],dp[22][22],sum[22]; int SUM(int l,int r) { return sum[r]-sum[l-1]; } int main() { int t,i,n,m,j,k; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); sum[0] = 0; for(i=1;i<=n;i++) { scanf("%d",&a[i]); sum[i] = sum[i-1] + a[i]; } for(i=0;i<=21;i++) { for(j=0;j<=i;j++) dp[i][j] = 1; for(j=i+1;j<=21;j++) dp[i][j] = 0; } for(i=1;i<=n;i++) { int s = 1; for(j=1;j<=i;j++) s *= a[j]; dp[i][i] = s; } for(i=1;i<=n;i++) { for(j=1;j<=i;j++) { int maxi = -1; for(k=j-1;k<i;k++) { maxi = max(maxi,dp[k][j-1]*SUM(k+1,i)); } dp[i][j] = max(maxi,dp[i][j]); } } printf("%d\n",dp[n][m]); } return 0; }
作者:whatbeg
出处1:http://whatbeg.com/
出处2:http://www.cnblogs.com/whatbeg/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
更多精彩文章抢先看?详见我的独立博客: whatbeg.com