问题描述
给出一个仅包含加减乘除四种运算符的算式(不含括号),如1+2*3/4,在保持运算符顺序不变的情况下,现在可以进行若干次如下操作:如果交换相邻的两个数,表达式值不变,那么你就可以交换这两个数。
现在你可以进行人一次操作,使得算式的数字序列字典序最小,然后输出结果,数字之间的字典序定义为若 a < b 则 a 的字典序小于 b。
输入描述
第一行包含一个整数n,表示算式的长度,即包含n个数字和n-1个运算符。(1<=n<=100000)
第二行包含一个含有n个非0整数和n-1运算符的算式,整数与运算符用空格隔开,运算符包含“+,-,*,/”,整数的绝对值不超过1000。
输出描述
按要求输出字典序最小的表达式,数字与符号直接用空格隔开。
实例1
输入
6
3 + 2 + 1 + -4 * -5 + 1
输出
1 + 2 + 3 + -5 * -4 + 1
问题分析
考点:冒泡排序, 对运算符顺序的理解
第一点: 题目中的相邻两个元素的互换排序,第一想到的就是冒泡排序。
冒泡排序:
比较相邻元素,如果反序,则进行交换。
void BubbleSort(int arr[], int n)
{
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
第二点: 考虑算式的运算的,例如 ‘a’ 5 ‘b’ 4 ‘c’ 3。想对5和4进行交换,我们分别考虑5 ‘b’ 4 在’b’分别为’ + ', ’ - ', ’ * ', ’ \ '时,‘a’ 和 ‘c’ 满足什么条件下可以进行交换。
-
当 ‘b’ = ’ + ’ 时,满足’a’ = ‘+’ 且 ‘c’ != ‘*’ or ‘/’;
-
当 ‘b’ = ’ - ’ 时,满足’a’ = ‘-’ 且 ‘c’ != ‘*’ or ‘/’;
-
当 ‘b’ = ’ * ’ 时,满足’a’ = ‘+’ or ‘-’ or ‘*’, ‘c’ = ‘any’;
-
当 ‘b’ = ’ / ’ 时,满足’a’ = ‘/’ , ‘c’ = 'any;
-
[ ] Concern:有没有可能即使破坏了算式的运算法则,进行数据交换,但最后的算式的值不变,这样只能用暴力求解了。
代码
#include<iostream>
#include<cstdio>
#include<vector>
#include<string.h>
using namespace std;
bool checkOperator (char a, char b, char c)
{
// E.g. 'a' 5 'b' 4 'c' 3
// And we consider separately when 'b' is equal to '+' '-' '*' '/'
// When 'b' = '+'; 'a' must = '+' also, and 'c' must != '*' or '/'
// e.g. + 5 + 4 + 3;
// + 5 + 4 - 3;
// if c = '*' or '/', can't switch 5 and 4
if (b == '+' && a == '+' && (c == '+' || c == '-'))
return true;
// When 'b' = '-'; 'a' must = '-' also, and 'c' must != '*' or '/'
// e.g. - 5 - 4 + 3;
// - 5 - 4 - 3;
// if c = '*' or '/', can't switch 5 and 4
else if (b == '-' && a == '-' && (c == '+' || c == '-'))
return true;
// When 'b' = '*'; 'a' = '+' or '-' or '*'; 'c' can = 'any'
// e.g. * 5 * 4 any 3;
// + 5 * 4 any 3;
// - 5 * 4 any 3;
// if a = '/', can't switch 5 and 4
else if (b == '*' && a != '/')
return true;
// When 'b' = '/'; 'a' must = '/'; and 'c' can = 'any'
// e.g. '/' 5 '/'4 any 3
// if a != '/', can't switch 5 and 4
else if (b == '/' && a == '/')
return true;
else
return false;
}
int main()
{
int n = 0;
cin >> n;
vector <int> S(n, 0);
vector <char> C(n+1, '+');
for (int i = 1; i < n + n; i++)
{
if (i % 2 == 0)
cin >> C[i/2];
else
cin >> S[(i -1)/2];
}
/*
for ( int i = 0; i < n; i ++)
{
cout<<S[i] << " " ;
cout<<C[i] << " " ;
}
*/
#if 1
for (int i = 0; i < n - 1; i ++)
{
for (int j = 0; j < n - i -1; j++)
{
if (S[j] > S[j+1] && checkOperator(C[j], C[j+1], C[j+2])) {
int temp = S[j];
S[j] = S[j+1];
S[j+1] = temp;
}
}
}
#endif
for ( int i = 0; i < n; i ++)
{
cout<<S[i] << " " ;
if (i < n-1)
cout<<C[i+1] << " " ;
}
cout << endl;
return 0;
}