最大的算式
源程序名 BIGEXP.??? (PAS,C,CPP)
可执行文件名 BIGEXP.EXE
输入文件名 BIGEXP.IN
输出文件名 BIGEXP.OUT
题目很简单,给出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之间)。
输出
输出文件仅一行包含一个整数,表示要求的最大的结果
样例
BIGEXP.IN
5 2
1 2 3 45
BIGEXP.OUT
120
说明
(1+2+3)*4*5=120
比较水的一道题,只是一些边界的判断有点问题。
f[l][r][k] =max{ f[l][i-1][p]*f[i][r][k-p-1],f[l][i-1][p]+f[i][r][k-p]}
[l,r]这个区间内使用了k个乘法,,最后一次做运算的最大值。
P为运算的地方,有一点要注意,就是如果多个转移,而且范围不同,最好把他们分开来写,这里就有问题,因为乘法的转移必须写在加法之前,因为乘法的范围较大,如果加法写在前面,则满足乘法的范围,但是已经跳过了。最好的方法就是分开写
WA80
#include <iostream>
using std::cout;
using std::cin;
const long oo = 0x7fff0000;
long long f[17][17][17];
long kk;
long nn;
void search(long l,long r,long k)
{
if(f[l][r][k]>=0) return;
for(long i=l+1;i<=r;i++)<=
{
for(long p=0;p<k+1;p++)&&p<i-l...k+1
{
if(r-i<k-p-1) continue;顺序
search(l,i-1,p);search(i,r,k-p-1);
f[l][r][k]>?= f[l][i-1][p]*f[i][r][k-p-1];
if(i-l<p) continue;///
if(r-i<k-p) continue;//
search(l,i-1,p);search(i,r,k-p);
f[l][r][k]>?= f[l][i-1][p]+f[i][r][k-p];
}
}
}
/*
void search(long l,long r,long k)
{
if(f[l][r][k]>0) return;
for(long i=l;i<r;i++)
{
for(long p=0;p<k&&p<=i-l;p++)
{
search(l,i,p);search(i+1,r,k-p-1);
f[l][r][k]>?= f[l][i][p]*f[i+1][r][k-p-1];
}
for(long p=0;p<k+1&&p<i-l;p++)
{
search(l,i,p);search(i+1,r,k-p);
f[l][r][k]>?= f[l][i][p]+f[i+1][r][k-p];
}
}
}*/
int main()
{
freopen("bigexp.in","r",stdin);
freopen("bigexp.out","w",stdout);
cin>> nn >> kk;
for(long i=1;i<nn+1;i++)
{
for(long j=i;j<nn+1;j++)
{
for(long k=1;k<kk+1;k++)
f[i][j][k]= -1;//
}
}
for(long i=1;i<nn+1;i++)
{
cin>> f[i][i][0];
}
search(1,nn,kk);
cout<< f[1][nn][kk];
}