蓝桥杯:后缀表达式

由于没有后台数据,答案不一定正确,仅供参考

问题描述

给定 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

思路(不一定对,仅供参考)

后缀表达式的运算顺序决定了她是变相可以带上括号的,意味着我们不能够直接最大减最小,比如

0 2

1 2 3
如果直接运算,那么会是 3-1 -2 = 0
但是实际结果是 2 - (1 - 3)= 4
这就需要我们通过改变运算顺序(加括号?)把减法化为加法再直接运算

有n个加号,m个减号

  • 假设m是偶数,那么可以转变为m/2个加号
  • 如果m是奇数,也可以转换为m/2个加号,只是最后会多出来一个减号,这个减号留给最小的数字即可

根据【 - (a - b) = + (b - a) 】

转换之后我们希望得到大的正数,这个正数的值就是两个数之间的差值,那么每次选取最大 ma x和最小 min 的数,然后做负负得正的变换 -(min - max) = +(max - min) 可以得到一个最大的差值(有点贪心的感觉?),这个变换需要消耗两个减号

  • 做 m/2 次上述变换,可以得到一些大的值
  • 值得注意的是,每次变换之后得到的大值,应该重新加入数组,作为下一次计算备选的数字之一
  • 做完减法变换之后做 n + m / 2 次加法,即可得到结果

代码(仅供参考)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

#include <iostream>
#include <algorithm>

using namespace std;

#define MAXLEN 100009
int nums[MAXLEN];
int n, m;
int len;

int main()
{
	cin>>n>>m;
	len = n + m + 1;
	for(int i=0; i<len; i++)
	{
		cin>>nums[i];
	}
	sort(nums, nums+len);
	
	// 如果减号刚好能够完全变为加号 
	if(m%2==0)
	{
		// 有m/2个新的加号 
		for(int i=0; i<m/2; i++)
		{
			int temp = nums[len-1] - nums[0];
			nums[0] = temp;
			len -= 1;
			sort(nums, nums+len);
		}
		
		// 加计算 
		for(int i=0; i<n+m/2; i++)
		{
			nums[0] += nums[len-1];
			len -= 1;
		}
		
		cout<<nums[0]<<endl;
	}
	// 如果减号不能刚刚好变成加号,不对第一个数处理
	else
	{
		for(int i=0; i<m/2; i++)
		{
			int temp = nums[len-1] - nums[1];
			nums[1] = temp;
			len -= 1;
			sort(nums+1, nums+len);
		}
		
		for(int i=0; i<n+m/2; i++)
		{
			nums[1] += nums[len-1];
			len -= 1;
		}
		
		// 多出来的一个减号在此运算 ↓ 
		cout<<nums[1]-nums[0]<<endl;
	}
	 
	return 0;
}


发布了51 篇原创文章 · 获赞 2 · 访问量 3367

猜你喜欢

转载自blog.csdn.net/weixin_44176696/article/details/104087795
今日推荐