前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >1467: [蓝桥杯2019初赛]后缀表达式

1467: [蓝桥杯2019初赛]后缀表达式

作者头像
可爱见见
发布2020-02-27 15:18:05
9590
发布2020-02-27 15:18:05
举报
文章被收录于专栏:卡尼慕卡尼慕

题目

给定N 个加号、M 个减号以及N + M + 1 个整数A1,A2,...,AN+M+1。

小明想知道在所有由这N 个加号、M 个减号以及N + M +1个整数凑出的合法的后缀表达式中,结果最大的是哪一个?

请你输出这个最大的结果。

例如使用1 2 3 + -,则“2 3 + 1 -” 这个后缀表达式结果是4,是最大的。

思路

读完题后,觉得很常规很简单。最大值无非就是先排序,把从最大的那一头开始相加,最小的那一头相减即可。按照题目的例子测试了一下,发现也没啥问题,结果一提交就错误了。

很显然,我没有考虑到可以有括号出现的情况。例如:

1 2

1 2 3 4

=》4 + 3 - (1 - 2) = 4 + 3 + 2 - 1

相当于只有一个减号。此时的题目,要么就没有减法,要么减法只能为1。

同时,允许有负数存在!因此我们需要根据减法数目与总个数之间的关系进行讨论。

如果负数数目不等于总个数,则所有负数可以转换为正数(负负得正)。

如果负数的数目等于总个数,那么必然会剩下一个负数不能转换成正数。

  1. 有减法(只能为1次,也就是排序后的最小值)
    1. 有负数
      1. 负数数目不等于总数目
      2. 负数数目等于总数目(选择绝对值最小负数)
    2. 没有负数
  2. 没有减法

代码

代码语言:javascript
复制
//1467: [蓝桥杯2019初赛]后缀表达式
#include <bits/stdc++.h>
using namespace std;
int a[200010]; 
int main(){
    int N, M;
    cin>>N>>M; //N个加号,M个减号
    int num = N + M + 1;
    int num_fu = 0;  //统计负数的个数 
    int sum = 0; 
    for(int i = 0; i < num; i++){
        cin>>a[i];
        sum += a[i];
        if(a[i] < 0) 
            num_fu++;
    }
    sort(a, a + num);
    if(M){
        //如果有减法,需要对比总数目与负数数目
        if(num_fu){
            //如果有负数
            if(num_fu == num){
                //负数的数目与总目相等,则负负得正,sum等于所有数的绝对值之和 
                for(int i = 0; i < num_fu - 1; i++){
                    sum -= 2 * a[i]; //2倍是因为前面sum减过一次了
                } 
            } 
            else{
                //负数的数目与总数目不相等,则必有一个负数不能转换成正数
                for(int i = 0; i < num_fu; i++){
                    sum -= 2 * a[i];
                } 
            }
        } 
        else{
            //如果没有负数,就只有一个负号起作用
            sum -= 2 * a[0]; 
        }
    }
    //如果没有减法,则最大值就直接是所有数的和
    cout<<sum;
    return 0;
} 
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-02-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 卡尼慕 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档