[ACM] n个数分为m部分,要求每部分的和乘起来积最大(区间DP)

A - 爱管闲事

春希非常爱管闲事,他每天都会抽空帮助一些同学,由于春希非常死板,出于公平性,春希不会先帮助后来找他的同学。

现在有n个同学需要他的帮助,虽然他很想一天之类帮助所有人,但毕竟精力有限,于是他决定分m天来帮助他们。

根据事情的重要性,春希帮助不同同学会有不同的快乐值,而春希获得的总的快乐值为每天获得的快乐值的乘积。

现在给出n和m,以及帮助完各同学时获得的快乐值,求春希能获得的最大快乐值。

Input

第一行为一个整数T,代表数据组数。

每组数据,第一行两个整数n,m。表示需要帮助的同学的数量,和天数。(1≤m≤min(n,10),1≤n≤20)

第二行为n个整数,表示帮助这个同学的获得的快乐值,每个快乐值不大于5。

Output

每组数据输出一行,一个整数,表示最大的快乐值。

Sample input and output

Sample Input Sample Output
1
5 3
3 2 1 4 5
125

解题思路:

dp[j][i]表示前j个数分为i部分的和的乘积的最大值。测试用例中(3+2)*(1+4)*5=125

三重循环。

dp[j][i]=max(dp[j][i],dp[k][i-1]*(sum[j]-sum[k]));

关键代码:

for(int i=1;i<=m;i++)
            for(int j=n;j>=i;j--)
                for(int k=i-1;k<j;k++)
        {
            dp[j][i]=max(dp[j][i],dp[k][i-1]*(sum[j]-sum[k]));
        }

代码:

#include <iostream>
#include <algorithm>
#include <string.h>
using namespace std;
const int maxn=25;
int dp[maxn][maxn];
int num[maxn],sum[maxn];
int t,n,m;

int main()
{
    cin>>t;
    while(t--)
    {
        cin>>n>>m;
        for(int i=0;i<=n;i++)
            for(int j=0;j<=m;j++)
            dp[i][j]=1;
        sum[0]=0;
        for(int i=1;i<=n;i++)
        {
            cin>>num[i];
            sum[i]=sum[i-1]+num[i];
        }
        for(int i=1;i<=m;i++)
            for(int j=n;j>=i;j--)
                for(int k=i-1;k<j;k++)
        {
            dp[j][i]=max(dp[j][i],dp[k][i-1]*(sum[j]-sum[k]));
        }
        cout<<dp[n][m]<<endl;
    }
    return 0;
}

一开始写的一维的,可是一直WA,不知道为什么,求解。

错误的一维代码:

#include <iostream>
#include <string.h>
#include <algorithm>
using namespace std;
int sum[25];
int num[25];
int dp[25];
int t;
int n,m;

int main()
{
    cin>>t;
    while(t--)
    {
        sum[0]=0;
        dp[0]=1;
        cin>>n>>m;
        for(int i=1;i<=n;i++)
        {
            cin>>num[i];
            sum[i]=sum[i-1]+num[i];
            dp[i]=1;
        }
        for(int i=1;i<=m;i++)
        {
            for(int j=n;j>=i;j--)
            {
                for(int k=i-1;k<j;k++)
                {
                    dp[j]=max(dp[j],dp[k]*(sum[j]-sum[k]));
                }
            }
        }
        cout<<dp[n]<<endl;
    }
    return 0;
}

[ACM] n个数分为m部分,要求每部分的和乘起来积最大(区间DP)

时间: 2024-08-05 15:28:35

[ACM] n个数分为m部分,要求每部分的和乘起来积最大(区间DP)的相关文章

2016 ACM/ICPC Asia Regional Shenyang Online 1009/HDU 5900 区间dp

QSC and Master Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 859    Accepted Submission(s): 325 Problem Description Every school has some legends, Northeastern University is the same. Enter

hdu4632 Palindrome subsequence 回文子序列个数 区间dp

Palindrome subsequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/65535 K (Java/Others)Total Submission(s): 4513    Accepted Submission(s): 1935 Problem Description In mathematics, a subsequence is a sequence that can be derived f

n个数分为两组,两组数的个数尽可能相等,差值最小

题目描述:对于有n个数的数组,分为两组,这两组的数的个数尽可能相等(不超过1),同时两组的数之和的差值最小. 这个题目使用类似0-1背包问题,思路:从k个数中选i个数,求所有可能的和,并把这些和放在flag中用true表示.(k,i,flag见代码) 1 public static void main(String[] args){ 2 int[] arr = {1 , 2 , 3 , 5 , 7 , 8 , 9}; 3 int n = 7; 4 int sum = 0; 5 for(int i

洛谷 P1026 统计单词个数 区间DP

题目描述 给出一个长度不超过200的由小写英文字母组成的字母串(约定;该字串以每行20个字母的方式输入,且保证每行一定为20个).要求将此字母串分成k份(1<k<=40),且每份中包含的单词个数加起来总数最大(每份中包含的单词可以部分重叠.当选用一个单词之后,其第一个字母不能再用.例如字符串this中可包含this和is,选用this之后就不能包含th). 单词在给出的一个不超过6个单词的字典中. 要求输出最大的个数. 输入输出格式 输入格式: 每组的第一行有二个正整数(p,k) p表示字串的

HDU ACM 4597 Play Game -&gt;区间DP+记忆化搜索

分析:两个人都足够聪明,因此每个阶段都拿最大的.dp[sa][ea][sb][eb]分别表示区间1的开始为sa,结束为ea,区间2的开始为sb,结束为eb时能拿到的最大值.之后分别从四个方向上拿,是个搜索的过程. [cpp] view plaincopyprint? #include<iostream> using namespace std; int dp[25][25][25][25];  //dp[sa][ea][sb][eb],分别表示区间1的开始,结束,区间2的开始,结束 int a

NYOJ 746 - 正整数n划分为m段,求m段的最大乘积 【区间DP】

整数划分(四) 时间限制:1000 ms  |  内存限制:65535 KB 描述 给出两个整数 n , m ,要求在 n 中加入m - 1 个乘号,将n分成m段,求出这m段的最大乘积 输入 第一行是一个整数T,表示有T组测试数据接下来T行,每行有两个正整数 n,m ( 1<= n < 10^19, 0 < m <= n的位数): 输出 输出每组测试样例结果为一个整数占一行 样例输入 2 111 2 1111 2 样例输出 11 121 #include <cstdio>

HDU4960Another OCD Patient(区间dp,分块后再DP)

Another OCD Patient Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 716    Accepted Submission(s): 270 Problem Description Xiaoji is an OCD (obsessive-compulsive disorder) patient. This morni

【题解】回文字

题目描述 如果一个单词从前和从后读都是一样的,则称为回文字.如果一个单词不是回文字,则可以把它拆分成若干个回文字.编程求一个给定的字母序列,最多要分割成几部分,使每一部分都回文字. 输入格式 一行,包含一个字符串.字符串由小写英文字母组成(a-z),长度不超过100. 输出格式 一行,为最少的回文字个数. 输入样例 anaban 输出样例 2 题解 区间dp.先判断当前子串是否是回文串,不是的话直接合并即可. #include <iostream> #include <algorithm

题解【POJ1651】Multiplication Puzzle

Description The multiplication puzzle is played with a row of cards, each containing a single positive integer. During the move player takes one card out of the row and scores the number of points equal to the product of the number on the card taken