南工ACM:最大的数

描述
小明和小红在打赌说自己数学学的好,于是小花就给他们出题了,考考他们谁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+1b>(b+1)a,所以选择1加a ; 当a>b,a+1b<(b+1)a,所以选择1加b. 综上,a ,b 哪个小1就加谁。但是,这也不一定完全对。
当a和b相同时,就加a而不加b,因为我们这是向左的贪心算法。
还有一种情况,就不能够“哪个小1就加谁”。

输入数据输出结果
11
1 11+1=2
1 1 11+1+1=3
1 1 1 11+1+1+1 = 2*2 =4
1 1 1 1 13*2 =6 > 5
1 1 1 1 1 1 1 13*3*2 =18 > 8
2 1 1 23*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;

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值