hdu 4192 (表达式求值)

时间:2023-03-09 22:47:37
hdu 4192 (表达式求值)

<题目链接>

<转载于 >>>  >

题目大意:

给你n个数,和一个最终的结果,再给你一个含有n个不同变量的式子,问你这个式子最终能否得到指定的答案。

解题分析:
我们可以利用全排列给这n个变量分配对应的值,然后就是对给定的式子进行表达式求值了。

对给定式子进行表达式求值有两种方法:

一、将中缀表达式转化为后缀表达式,然后对后缀表达式进行计算

(1)、把中缀表达式转换为后缀表达式算法的基本思路是从头到尾地扫描中缀表达式中的每个字符,对于不同类型的字符按不情况进行处理。
1、先定义一个工作数组,用来存储转换之后的后缀表达式,定义一个栈,用来存储运算符。(越往栈顶优先级越高的原则)可以先定义一个‘#’优先级为0存入栈底
2、扫描:若遇到的是操作数,直接存入工作数组中,若遇到运算符,将该运算符与栈顶元素比较,若该运算符优先级高,直接入栈,否则,
   弹栈,直到栈顶元素优先级比该运算符优先级低,出栈后的运算符存入工作数组里。‘(’进栈时要定义低优先级,出现‘)’则弹栈。
3、扫描到中缀表达式结束符'\0'时,把栈中剩余的运算符弹出存入工作数组中。

(2)、计算后缀表达式的思路是:
1、从左向右扫描后缀表达式,遇到运算符就把栈顶两个元素出栈,执行运算,得到的结果再入栈.
例:(a+b)*c的逆波兰式为ab+c*,假设计算机把ab+c*按从左到右的顺序压入栈中,并且按照遇到运算符就把栈顶两个元素出栈,执行运算,
得到的结果再入栈的原则来进行处理,那么ab+c*的执行结果如下:
  1)a入栈(0位置)
  2)b入栈(1位置)
  3)遇到运算符"+",将a和b出栈,执行a+b的操作,得到结果d=a+b,再将d入栈(0位置)
  4)c入栈(1位置)
  5)遇到运算符"*",将d和c出栈,执行d*c的操作,得到结果e,再将e入栈(0位置)

二、直接计算中缀表达式思路:
1、定义两个栈,一个用来存取运算符,一个用来存取操作数。
2、从左向右扫描表达式,遇到操作数,直接存入操作数栈中,遇到运算符,将该运算符与运算符栈顶元素比较,若该运算符优先级高,直接入栈,否则弹栈,同时取操作数栈的最上面两个元素和弹出的运算符进行运算,结果压入操作数栈中。直到运算符栈顶元素优先级比该运算符
优先级低。
3、扫描完毕后,运算符依次出栈。注意:只要有一个运算符出栈,就要去操作数栈中的最上面两个元素进行计算,并把结果压入操作数栈中。

 #include <iostream>
 #include <cstdio>
 #include <algorithm>
 #include <cstring>
 #include <string>
 #include <stack>
 #include <map>
 using namespace std;
  + ;
 map<char, int> mpa;

 string change(string str) {
     string ans;
     stack<char> s;
     map<char, int> op;
     op[; op[;   //给这些符号分配优先级
     op[; op[;
     op[;
     s.push('#');
     ; i < str.size(); ++i) {
         if(str[i] >= 'a' && str[i] <= 'z') ans += str[i];
         else {
             if(str[i] == ')') {
                 do {
                     ans += s.top();
                     s.pop();
                 } while(s.top() != '(');
                 s.pop();  // 弹出(
             }
             else if(op[str[i]] > op[s.top()])    //如果当前符合优先级大于栈顶,则入栈
                 s.push(str[i]);
             else {
                 do {
                     if(s.top() == '(') break;
                     ans += s.top();
                     s.pop();
                 } while(op[s.top()] >= op[str[i]]);
                 s.push(str[i]);
             }
         }
     }
     while(s.top() != '#') {
         ans += s.top();
         s.pop();
     }
     return ans;
 }

 int slove(string str) {
     stack<int> s;
     ; i < str.size(); ++i) {
         if(str[i] >= 'a' && str[i] <= 'z') s.push(mpa[str[i]]);
         else {
             int a, b;
             b = s.top(); s.pop();
             a = s.top(); s.pop();
             if(str[i] == '+') s.push(a + b);
             else if(str[i] == '-') s.push(a - b);
             else if(str[i] == '*') s.push(a * b);
         }
     }
     return s.top();
 }

 int n, k;
 int a[maxn];
 string ss;

 int main() {
     while(scanf("%d", &n) != EOF && n) {
         ; i < n; ++i)
             scanf("%d", &a[i]);
         scanf("%d", &k);
         cin >> ss;
         sort(a, a + n);   //因为下面要进行全排列,所以这里要排序
         string res = change(ss);  //得到转换后的后缀表达式
         bool ok = false;
         do {
             ;
             ; i < ss.size(); ++i)
                 if(ss[i] >= 'a' && ss[i] <= 'z') mpa[ss[i]] = a[r++];  //给每个变量分配实际数据
             int ans = slove(res);   //根据分配的数据算出结果
             if(ans == k) {
                 ok = true;
                 break;
             }
         } while(next_permutation(a, a + n));     //对a进行全排列,得到所有变量的分配情况
         if(ok) printf("YES\n");
         else printf("NO\n");
     }
     ;
 }

2018-10-05