算法训练 最大的算式
时间限制:1.0s 内存限制:256.0MB
问题描述
题目很简单,给出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=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
1 2 3 4 5
样例输出
120
样例说明
(1+2+3)*4*5=120
注意:动态规划的初始化不要忘记
/* 注意: 1.使用搜索找到乘号的位置 2.使用动态规划找到最大的值 3.使用long long对结果进行保存 */ #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; long long a[20],op[20],n,k,dp[20][20],maxn; void dfs(int dep,int pos); void calc(); int main(void){ cin >> n >> k; for(int i=1;i<=n;i++) cin >> a[i]; dfs(1,1); cout << maxn; return 0; } void dfs(int dep,int pos){ if(dep == k+1){ calc(); } for(int i=pos;i<n;i++){ op[i]=1; if(n-i-1 >= k-dep) dfs(dep+1,i+1); op[i]=0; } } void calc(){ memset(dp,0,sizeof(dp)); for(int i=1;i<=n;i++) dp[i][i] = a[i]; for(int len=2;len<=n;len++){ for(int i=1;i<=n-len+1;i++){ int j=i+len-1; for(int k=i;k<j;k++){ long long data; if(op[k] == 0) data = dp[i][k] + dp[k+1][j]; if(op[k] == 1) data = dp[i][k] * dp[k+1][j]; dp[i][j]=max(dp[i][j],data); } } } maxn=max(maxn,dp[1][n]); }