动态规划——求最大乘积

1.问题描述

插入乘号
Time Limit: 1000 MS Memory Limit: 1000 KB

Description

给出N个1-9的数字 (v1,v2,…,vN), 不改变它们的相对位置, 在中间加入K个乘号和N-K-1个加号, 括号随便加, 
使最终结果最大。因为乘号和加号一共就是N-1个,所以恰好每两个相邻数字之间都有一个符号。
例如: N=5, K=2,5个数字分别为1、2、3、4、5,可以进行如下运算: 
1*2*(3+4+5)=24 
1*(2+3)*(4+5)=45 
(1*2+3)*(4+5)=45
等等.

Input

第一行输入M(M<=10)表示有M组数据。每组数据输入两整数N和K(N<=20, K<20), 接下来输入N个1-9的数字。

Output

输出M行正整数,第i行表示第i组数据的最大结果, 你可能需要用long long类型存储结果。

Sample Input

2
5 2
1 2 3 4 5 
6 3
1 2 3 4 5 6

Sample Output

120
720

2.思路分析:

  1. 首先,我们输入测试用例的数量 T。
  2. 对于每个测试用例,我们输入数组的长度 N 和可取的最大元素个数 K。
  3. 接下来,我们输入数组的元素,存储在 arr 数组中。
  4. 我们创建一个动态规划数组 dp,其中 dp[i][j] 表示前 i 个元素中选择 j 个元素进行乘积的最大值。
  5. 初始化动态规划数组的第一列 dp[i][0],表示前 i 个元素中不选择任何元素的乘积,即取前缀和。
  6. 对于每个 i(从 2 到 N),我们遍历可取的元素个数 j(从 1 到 min(K, i-1)):
    • 对于每个 k(从 2 到 i),我们计算 dp[i][j] 的值,即选择 k 作为最后一个元素,将问题分解为两部分:
      • 前 k-1 个元素中选择 j-1 个元素进行乘积,即 dp[k-1][j-1]。
      • k 到 i 之间的元素的乘积,即 sum(arr, k, i)。
      • 取上述两部分的乘积的最大值,更新 dp[i][j]。
  7. 最后,输出 dp[N][K],即最大乘积和。

这段代码利用动态规划的思想,通过填充动态规划数组 dp 来计算最大乘积和。每个状态的计算依赖于前面已经计算的状态,通过递推得到最终结果。

3.代码示例

#include<iostream>
#include<cmath>
#include<limits.h>
const int MAX = INT_MAX;
using namespace std;
int sum(int a[], int s, int e)
{
	int sum = 0;
	for (int i = s; i <= e; i++)
		sum += a[i];
	return sum;
}
int main()
{
	int T;
	cin >> T;
	while (T--)
	{
		long long dp[21][21] = { 0 };
		int arr[21];
		int N, K;
		cin >> N >> K;
		for (int i = 1; i <= N; i++)
		{
			cin >> arr[i];
		}
		for (int i = 1; i <= N; i++)
			dp[i][0] = sum(arr, 1, i);
		
			for (int i = 2; i <= N; i++) {
				for (int j = 1; j <= min(K,i-1); j++){
					for (int k = 2; k <= i; k++) 
				{
					dp[i][j] = max((dp[k-1][j-1] * (sum(arr,k,i))),dp[i][j]);
				}
			}
		}
		cout << dp[N][K] << endl;
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/lyhizjj/article/details/130749991
今日推荐