描述
小明和小红在打赌说自己数学学的好,于是小花就给他们出题了,考考他们谁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,他只有左边的数可以加,所以这两种情况要另外讨论。
还有一点,要考虑是否在代码里另外讨论i=1且n=1的情况。int a[10]={0}仅仅对a[0]初始化。当时程序不知道为什么自动将a全部弄成0,当时我们代码在处理i=1且n=1的情况时会越界,访问a[2],但是n=1没有a[2]。当时程序不知道为什么自动将a全部弄成0,所以没发生错误。但是提交后,就一直出错(被坑了2个小时)。
#include<stdio.h>
int main()
{
int n=0;
int i=0,j=1;
int sum=1;
int a[10000+1];
int b[10000+1];
while(scanf("%d",&n)!=EOF)
{
for(i=1;i<=n;i++)
{
scanf("%d",a+i);
}
sum=1;
for(i=1,j=1;i<=n;i++)
{
if(a[i]!=1)
{
b[j]=a[i];
j++;
}
else
{
if(i==1)
{
if(n==1)//n=1且i=1的情况
{
b[j]=a[i];
j++;
break;
}
b[j]=a[i]+a[i+1];
i++;
j++;
continue;
}
if(i==n || b[j-1]<=a[i+1])
{
b[j-1]=b[j-1]+a[i];
}
else
{
if(b[j-1]==2)
{
b[j-1]=b[j-1]+a[i];
}
else
{
b[j]=a[i]+a[i+1];
i++;
j++;
}
}
}
}
j=j-1;
for(i=1;i<=j;i++)
{
sum=(sum*b[i])%10086;
}
printf("%d\n",sum);
}
return 0;
}

561

被折叠的 条评论
为什么被折叠?



