第十届蓝桥杯省赛java B组后缀表达式

试题 I: 后缀表达式

时间限制: 1.0s 内存限制: 512.0MB 本题总分:25 分
【问题描述】
给定 N 个加号、M 个减号以及 N + M + 1 个整数 A1, A2, · · · , AN+M+1,小
明想知道在所有由这 N 个加号、M 个减号以及 N + M + 1 个整数凑出的合法的
后缀表达式中,结果最大的是哪一个?
请你输出这个最大的结果。
例如使用1 2 3 + -,则 “2 3 + 1 -” 这个后缀表达式结果是 4,是最大的。
【输入格式】
第一行包含两个整数 N 和 M。
第二行包含 N + M + 1 个整数 A1, A2, · · · , AN+M+1【输出格式】
输出一个整数,代表答案。
【样例输入】
1 1
1 2 3
【样例输出】
4
【评测用例规模与约定】
对于所有评测用例,0 ≤ N, M ≤ 100000,ˈ 109 ≤ Ai ≤ 109。

分析:
/为了便于处理表达式,常常将普通表达式(称为中缀表示)
转换为后缀{运算符在后,如X/Y写为XY/表达式。
在这样的表示中可以不用括号即可确定求值的顺序,
如:(P+Q)
(R-S) → PQ+RS-*。后缀表达式的处理过程如下:
扫描后缀表达式,凡遇操作数则将之压进堆栈,
遇运算符则从堆栈中弹出两个操作数进行该运算,将运算结果压栈,然后继续扫描,
直到后缀表达式被扫描完毕为止,此时栈底元素即为该后缀表达式的值。

解题思路:
①减号个数为0,那么没有办法只能全加

②减号个数等于负数个数,那么减去所有负数就能得到最大结果

③减号个数小于负数个数,可以通过加号的补充来达到上一种情况的效果的

比如(6 5 -4 -3 -2 -1),有1个减号,那么可以变成 6 + 5 - ( -4 + -3 + -2 + -1 ) ;有2个减号,那么可以变成 6 + 5 - -4 - ( -3 + -2 + -1 ) ;有3个减号,那么可以变成6 + 5 - -4 - -3 - ( -2 + -1 )

④减号个数大于负数个数,分两种情况,第一种全是正数的情况,就减掉最小的数然后进行相加。第二种存在负数的情况,就把所有数的绝对进行相加
例如:输入2 4
-1 -2 -3 4 5 6 7
可以这样组合:4-((-3)-7-2)+5+6 -(-1)
输入0 4
5 - (1-2-3-4) = 5+4+3+2-1 = 13

综上所述,第一种是直接求和,第二种和第三种是可以合并的,即求绝对值和。

/*为了便于处理表达式,常常将普通表达式(称为中缀表示)
转换为后缀{运算符在后,如X/Y写为XY/表达式。
在这样的表示中可以不用括号即可确定求值的顺序,
如:(P+Q)*(R-S) → PQ+RS-*。后缀表达式的处理过程如下:
扫描后缀表达式,凡遇操作数则将之压进堆栈,
遇运算符则从堆栈中弹出两个操作数进行该运算,将运算结果压栈,然后继续扫描,
直到后缀表达式被扫描完毕为止,此时栈底元素即为该后缀表达式的值。

解题思路:
①减号个数为0,那么没有办法只能全加

②减号个数等于负数个数,那么减去所有负数就能得到最大结果

③减号个数小于负数个数,可以通过加号的补充来达到上一种情况的效果的

比如(6 5 -4 -3 -2 -1),有1个减号,那么可以变成 6 + 5 - ( -4 + -3 + -2 + -1 ) ;有2个减号,那么可以变成 6 + 5 - -4 - ( -3 + -2 + -1 )  ;有3个减号,那么可以变成6 + 5 - -4 - -3 - ( -2 + -1 )  

④减号个数大于负数个数,分两种情况,第一种全是正数的情况,就减掉最小的数然后进行相加。第二种存在负数的情况,就把所有数的绝对进行相加

综上所述,第一种是直接求和,第二种和第三种是可以合并的,即求绝对值和。
*/

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

public class test9 {
	public static void main(String[] args) throws IOException{
		int[] positive = new int[100000+1];  //储存正数的数组,int的取值范围2147483648
		int[] negative = new int[100000+1];
		int po = 0;    //正数的个数
		int ne = 0;	   //负数的个数
		int n = 0;    //正号的个数
		int m = 0;	  //负号的个数
		long sum = 0;
		n = MyReader.nextInt();
		m = MyReader.nextInt();
		for(int i=0; i<n+m+1; i++){  //读取数据
			int temp = MyReader.nextInt();
			if(temp>0)  positive[po++] = temp;
			else negative[ne++] = temp;
		}
		if(m<=0){    //负号的个数小于零, 将所有的数进行相加
			for(int i=0; i<po; i++){  
				sum = sum + positive[i];
			}
			for(int i=0; i<ne; i++){
				sum = sum + negative[i];
			}
		}
		if(m<=ne&&m>0){  //负号的个数小于等于负数的个数,求绝对值和。
			for(int i=0; i<po; i++){
				sum = sum + positive[i];
			}
			for(int i=0; i<ne; i++){
				sum = sum + Math.abs(negative[i]);
			}
		}
		if(m>ne){  //负号的个数大于负数的个数,先求和再减去多余负号个数的小正数。
			Arrays.sort(positive,0,po);  //将数组进行排序,默认是正序
			//不能写成Arrays.sort(a),因为这是对整个数组进行排序。数组中有很多是无效的零,
			//因为定义的时候将数组的大小设定为题目给的大上限值。默认值都是零          
			if(ne==0){        //全是正数,减掉最小的数,把其他数的绝对值进行相加
				sum = sum - positive[0];
				for(int i=1; i<po; i++){   //将剩下的正数进行相加
					sum = sum + positive[i];
				}
				for(int i=0; i<ne; i++){
					sum = sum + Math.abs(negative[i]);
				}
			}
			else{  //存在负数,  将所有数的绝对值进行相加
				for(int i=0; i<po; i++){
					sum = sum + positive[i];
				}
				for(int i=0; i<ne; i++){
					sum = sum + Math.abs(negative[i]);
				}
			}
			
		}
		System.out.println(sum);
	}
}

class MyReader{
	static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));//定义字符流
	static StringTokenizer tokenizer = new StringTokenizer("");
	static String nextLine() throws IOException{// 读取下一行字符串
		return reader.readLine();
	}
	static String next() throws IOException {// 读取下一个字符串
		while (!tokenizer.hasMoreTokens()) {
			tokenizer = new StringTokenizer(reader.readLine());
		}
		return tokenizer.nextToken();
	}

	static int nextInt() throws IOException {// 读取下一个int型数值
		return Integer.parseInt(next());
	}

	static double nextDouble() throws IOException {// 读取下一个double型数值
		return Double.parseDouble(next());
	}
}

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

逍遥自在”

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值