演算法訓練 最大的算式 藍橋杯
阿新 • • 發佈:2019-01-10
問題描述
題目很簡單,給出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 樣例說明
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
首先有一個猜想,由a*(b+c)*d>a*b+c*d,猜想任意一個序列,連加優先計算,所得結果最大,我們只需要在這些加號優先計算的序列中尋找答案就可以了。
是否適合使用動態規劃
(1)滿足最優子結構
子問題 求下標從x到結束的序列,新增符號以後得到的最大值,記為f(x)
另外,下標從x到y犯人序列,連加得到的和記為g(x,y)子問題
那麼,f(x)=max{g(top,i-1)*f(i)}
其中,i表示序列(下標從top到N-1)第一個乘號後的數的下標,取遍top+1到N-1
2)滿足重疊子問題
大量f(i)需要重複計算
具體操作注意答案數值巨大,用long long;乘號數量限制,加上可使用乘號數量這個引數
#include<stdio.h> int a[100],c[100]={0}; int N,K; long long b[100][100]={0}; long long g(int top,int end){ int i; long long q=0; for(i=top;i<=end;i++) q+=a[i]; return q; } long long f(int begin,int k){ int i; long long t,ans=0; if(b[begin][k])return b[begin][k]; if(k==0) return g(begin,N-1); if(begin==N-1&&k) return 0; for(i=begin+1;i<=N-1;i++){ if(ans<(t=(g(begin,i-1)*f(i,k-1)))){ ans=t; } } return b[begin][k]=ans; } int main(){ int i; scanf("%d%d",&N,&K); for(i=0;i<N;i++){ scanf("%d",&a[i]); } printf("%lld\n",f(0,K)); return 0; }