藍橋杯 演算法訓練 ALGO-116 最大的算式 動態規劃 資源分配型別(最大乘積)
阿新 • • 發佈:2018-12-21
演算法訓練 最大的算式
時間限制:1.0s 記憶體限制:256.0MB
問題描述
題目很簡單,給出N個數字,不改變它們的相對位置,在中間加入K個乘號和N-K-1個加號,(括號隨便加)使最終結果儘量大。因為乘號和加號一共就是N-1個了,所以恰好每兩個相鄰數字之間都有一個符號。例如:
N=5,K=2,5個數字分別為1、2、3、4、5,可以加成:
12(3+4+5)=24
1*(2+3)(4+5)=45
(12+3)*(4+5)=45
……
輸入格式
輸入檔案共有二行,第一行為兩個有空格隔開的整數,表示N和K,其中(2<=N<=15, 0<=K<=N-1)。第二行為 N個用空格隔開的數字(每個數字在0到9之間)。
輸出格式
輸出檔案僅一行包含一個整數,表示要求的最大的結果
樣例輸入
5 2
1 2 3 4 5
樣例輸出
120
樣例說明
(1+2+3)45=120
分析:既然是動態規劃,就按照動態規劃的思路來就可以了,方法其實並不唯一。這裡我引用網上的一篇思路,個人感覺比我自己的要好。
思路:設
為前
個數的總和,那麼從
到
的總和為
。設
表示前
個數中有
個乘號的最大的結果,則想要知道
,可以嘗試從第二個數的前面一直到最後一個數的前面依次新增乘號,將最大的結果儲存至
中。就可以得到狀態轉移方程為:
為插入相乘的兩個數的後一個數字的座標。
注:本篇內容轉自https://blog.csdn.net/liuchuo/article/details/51990007
#include <iostream>
using namespace std;
#define max(a, b) a > b ? a : b;
long long dp[16][16];
int sum[16];
int main()
{
int n, k;
cin >> n >> k;
for(int i = 1; i <= n; i++)
{
int temp;
cin >> temp;
sum[i] = sum[i-1] + temp;
dp[i][0] = sum[i];
}
for(int i = 2; i <= n; i++)
{
for(int j = 1; j <= i-1 && j <= k; j++)
{
for(int l = 2; l <= n; l++)
{
dp[i][j] = max(dp[i][j], dp[l-1][j-1] * (sum[i] - sum[l-1]));
}
}
}
cout << dp[n][k];
return 0;
}