描述
小明和小红在打赌说自己数学学的好,于是小花就给他们出题了,考考他们谁NB,题目是这样的给你N个数
在这n个数之间添加N-1个*或+,使结果最大,但不可以打乱原顺序,请得出这个结果
如
1 3 5
结果是(1+3)*5=20;最大
可以添加若干个括号,但一定要保证配对,但是每两个数之间只可能有一个*或+
数列最前和最后不应有+或乘
小明想赢小红但是他比较笨,请你帮帮他
输入
多组测试数据以EOF结束,每组有一个n(n<10000),然后有n个正整数a[i](1<=a[i]<=20)
输出
输出最大的结果由于结果比较大,结果对10086取余
样例输入
3 1 2 3 3 5 1 2
样例输出
9 15
贪心算法
就是向左贪心。从左至右,遇到第i个数,选择当时最好的方案(*或+),用子问题(前i-1个数的最大值)来∗/+
第i个数,从而得到最新子问题(前i个数的最大值)。只是在下面的一些特殊情况下,要另外处理。
一般情况下,相乘比相加得到的数值大。所以,一般用乘法。但是也有特殊情况,那就1和2。
对于数值1,1*a=a ,但是1+a=a ,所以遇到1时我们要用加法,而不是乘法。
但是,是让1加他左边的数,还是让1加他右边的数呢?
这就要讨论了。对于 a 1 b 。 当a<b,(a+1)∗b>(b+1)∗a
,所以选择1加a ; 当a>b,(a+1)∗b<(b+1)∗a
,所以选择1加b. 综上,a ,b 哪个小1就加谁。但是,这也不一定完全对。
当a和b相同时,就加a而不加b,因为我们这是向左的贪心算法。
还有一种情况,就不能够“哪个小1就加谁”。
输入数据 | 输出结果 |
---|---|
1 | 1 |
1 1 | 1+1=2 |
1 1 1 | 1+1+1=3 |
1 1 1 1 | 1+1+1+1 = 2*2 =4 |
1 1 1 1 1 | 3*2 =6 > 5 |
1 1 1 1 1 1 1 1 | 3*3*2 =18 > 8 |
2 1 1 2 | 3*3=9 > 2*2*2=8 |
从上表可以看出,当全1的个数小于或等于4时 ,加分比乘法优;但是当大于4时,我们会尽可能的“凑3”,3个1相加,3个1相加 这样才能够最优的。
所以1+2 比1+1会得到更好的效果
所以 当有2 1 a 这样时,时,无论a为多少,直接让1与2相加。
当然,第一个数如果为1,他只有右边的数可以加;最后一个数如果为1,他只有左边的数可以加,所以这两种情况要另外讨论。
//向左的贪心算法。
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int a[10005],b[10005];
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
int i,j;
for (i=1;i<=n;i++)
scanf("%d",&a[i]);
for (i=1,j=1;i<=n;i++)
{
if (a[i]!=1)
{
b[j] = a[i];
j++;
}
else
{
if (i==1)
{
if (n==1)
{
b[j] = a[i];
j++;
break;
}
else
{
b[j] = a[i] + a[i+1];
j++;
i++;
continue;
}
}
if (i==n || b[j-1]<=a[i+1])
b[j-1] += a[i];
else
{
if (b[j-1]==2)
b[j-1] += a[i];
else
{
b[j] = a[i] + a[i+1];
i++;
j++;
}
}
}
}
int sum = 1;
for (i=1;i<j;i++)
sum = (sum * b[i]) % 10086;
printf("%d\n",sum);
}
return 0;
}