经典表达式求值,立马想到使用堆栈实现
在遍历当前算术表达式字符串时会有五种情况:
- 当前字符是数字。如果当前字符是数字的话,那么就直接将其转换成对应的整型数并压入运算数栈中。
- 当前字符是加号,由于加法的优先级低于乘法和除法,所以不能直接进行加法运算,要先把加号压入运算符栈中。
- 当前字符是减号减法的优先级同加法一样,也不能直接进行运算。此处为了后续操作方便,统一将a-b的形式转换成a+(-b)的形式来运算减法。即将加号压入运算符栈中,将第二个运算数取反之后压入运算数栈中。
- 当前字符是乘号乘法在本题中是优先级最高的,可以直接进行运算。去运算数栈的栈顶元素和乘号后面的那个运算数做乘法,将结果再压入运算数栈中。
- 当前字符是除号除法的优先级同乘法一样,操作同上。
在遍历完算术表达式时,说明式子中的乘除运算都已经完成,下面只剩下加法(减法已经转换成加法),直到运算符栈为空,最终的结果就是运算数的栈顶元素。最后拿这个数和24来进行比对即可。
#include <iostream> #include <string> #include <string.h> #include <stack> using namespace std; //二十四点游戏 ,特别注意运算符的优先级问题!!!用堆栈来解决 int main() { int n; //表达式的个数 string str; //暂存当前表达式 int i, j; int result[100] = {0}; //1代表计算结果是24, 0代表不是 stack<int> num; //运算数栈 stack<char> op; //运算符栈 cin >> n; for (i = 0; i < n; i++) { cin >> str; for (j = 0; j < str.length(); j++) { if (isdigit(str[j])) { //是数字 num.push(str[j] - '0'); } else if (str[j] == '+') { op.push('+'); } else if (str[j] == '-') { //将减法转换成加法 op.push('+'); num.push(-(str[j + 1] - '0')); j++; } else if (str[j] == 'x') { //直接计算乘法 int num1 = num.top(); num.pop(); num.push(num1 * (str[j + 1] - '0')); j++; } else if (str[j] == '/') { //直接计算除法 int num1 = num.top(); num.pop(); num.push(num1 / (str[j + 1] - '0')); j++; } } while (!op.empty()) { int num1 = num.top(); num.pop(); int num2 = num.top(); num.pop(); num.push(num1 + num2); op.pop(); } if (num.top() == 24) { result[i] = 1; } num.pop(); //清空操作数栈 } for (i = 0; i < n; i++) { if (result[i] == 0) { cout << "No" << endl; } else { cout << "Yes" << endl; } } return 0; }
思路2:模拟
我们可以利用迭代来模拟计算的过程,即先使用两个数组存储运算符与操作数,然后优先计算乘除,每次都直接将结果放在操作数数组中,但是每次都需要更新当前操作数后面的运算符与操作数
/* CCF201903-2 二十四点 */ #include <stdio.h> /* 判定24点函数 */ int judge(char s[]) { int a[4], i, j; char op[3]; /* 从输入取出数和运算符 */ for(i = 0; i < 4; i++) a[i] = s[i * 2] - '0'; for(i = 0; i < 3; i++) op[i] = s[i * 2 + 1]; int k = 3; /* 总共计算3次 */ /* 先计算乘(x)和除(/) */ for(i = 0; i < k; i++) if(op[i] == 'x' || op[i] == '/') { if(op[i] == 'x') a[i] = a[i] * a[i + 1]; else a[i] = a[i] / a[i + 1]; for(j = i + 1; j < k; j++) { op[j - 1] = op[j]; a[j] = a[j + 1]; } k--, i--; } /* 再计算加(+)和减(-) */ int ans = a[0]; for(i = 0; i < k; i++) if(op[i] == '+') { ans = a[i] + a[i + 1]; a[i + 1] = ans; } else { ans = a[i] - a[i + 1]; a[i + 1] = ans; } return ans == 24; } int main(void) { int n; char s[7 + 1]; scanf("%d", &n); while(n--) { scanf("%s", s); printf(judge(s) ? "Yes\n" : "No\n"); } return 0; }