Fork me on GitHub

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;
}
View Code

 

posted @ 2014-05-31 20:40  whatbeg  阅读(309)  评论(0编辑  收藏  举报