1. 程式人生 > >算法訓練 最大的算式

算法訓練 最大的算式

括號 最大值 using data pac ret 文件 += 方程

問題描述   題目很簡單,給出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[p-1][j-1]*(dp[i][0]-dp[p-1][0])); p表示第j個乘號在第p個數前面; 方程的意思是:前面i個數使用j個乘號的最大值等於前面p-1個數使用j-1個乘號的最大值乘以後面所有數的和;所以p前面的乘號是最後一個乘號,通過循環最後一個乘號的位置找到最大值; (需要註意的是:例如需要5個乘號,最後一個乘號會從第2個數前面開始循環,這時dp[p-1][j-1]就是dp[1][4],顯然前面一個數不可能有4個乘號,所以dp[1][4]不存在,但dp[1][4]開始時被初始化為0,這樣就不需要擔心這種情況的成為最大值)
#include <string
.h> #include<iostream> #include<stdio.h> #include<vector> #include<queue> #include <algorithm> #include<math.h> #define INF 1<<30 using namespace std; long long dp[20][20]; int main() { int n,k; cin>>n>>k; long long sum=0,s; for(int i=1
;i<=n;i++){ cin>>s; sum+=s; dp[i][0]=sum; } for(int i=1;i<=n;i++){ for(int j=1;j<=i-1&&j<=k;j++){ for(int p=2;p<=i;p++){ dp[i][j]=max(dp[i][j],dp[p-1][j-1]*(dp[i][0]-dp[p-1][0])); } } } cout
<<dp[n][k]<<endl; return 0; }

算法訓練 最大的算式