1. 程式人生 > >藍橋杯-演算法訓練- ALGO-116-最大的算式

藍橋杯-演算法訓練- ALGO-116-最大的算式

最大的算式

問題描述
  題目很簡單,給出N個數字,不改變它們的相對位置,在中間加入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
  ……
輸入格式
  輸入檔案共有二行,第一行為兩個有空格隔開的整數,表示N和K,其中(2<=N<=15, 0<=K<=N-1)。第二行為 N個用空格隔開的數字(每個數字在0到9之間)。
輸出格式


  輸出檔案僅一行包含一個整數,表示要求的最大的結果
樣例輸入
5 2
1 2 3 4 5
樣例輸出
120
樣例說明
  (1+2+3) * 4 * 5=120

演算法分析
典型的區間動態規劃問題
dp[i][j]表示前i個數字,當有j個乘號的時候最大的結果
狀態轉移方程:dp[i][j] = max(dp[i][j],dp[l-1][j-1]*(m[i]-m[l-1]))
  
程式碼

/*
最大的算式
*/
#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;
#define MAX_N 16 static long long m[MAX_N]; static long long dp[MAX_N][MAX_N]; void Max_equ(int n,int k) { for(int i = 2;i <= n;i ++ ){ //從前兩個數開始拓展到n個 int index = min(i - 1,k); //找出運算子和*的最小值 for(int j = 1;j <= index;j ++ ) for(int l = 2;l <= i;l ++ ) dp[i][j] = max(dp[i][j],dp[
l-1][j-1]*(m[i]-m[l-1])); } cout << dp[n][k] << endl; } int main() { int n,k; int a; cin >> n >> k; for(int i = 1;i <= n;i ++ ){ cin >> a; if(i == 1) { m[i] = a; dp[i][0] = m[i]; } else{ m[i] = m[i-1] + a; dp[i][0] = m[i]; } } Max_equ(n,k); return 0; }