CSP201903-02 二十四点

法1:利用两个栈,一个操作数栈,一个运算符栈,进行表达式求值

import java.util.Scanner;
import java.util.Stack;

public class Main{
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        Stack<Character> opt = new Stack<>();
        Stack<Integer> num = new Stack<>();
        
        int n = in.nextInt();
        for(int i=0; i<n;i++){
            String s = in.next(); //in.next() 和 in.nextLine()的区别?
            for(int j=0;j<s.length();j++){
                if(j%2==0){ //偶数位为操作符,奇数位为数字,这里奇数位在下标表示为0,2,4(1,3,5……)
                    num.push((int)s.charAt(j)-'0'); //数字
                }else{
                    if(opt.empty()){ //第一次往操作符栈里push的情况
                        opt.push(s.charAt(j));//操作符
                    }else{ //要判断优先级并注意操作符栈不空
                        while(!opt.empty() && priority(opt.peek(),s.charAt(j))>0){
                            //若该操作符优先级小于等于操作符栈顶优先级,则操作符栈栈顶出栈并与数字栈出栈的
                            //两元素运算后,将结果push到数字栈中,
                            //直到该操作符优先级大于操作符栈顶或栈已空为止
                            numAndOptPop(num,opt); //本字符小于等于栈顶情况
                        }
                        opt.push(s.charAt(j)); //将该符入操作符栈 //大于栈顶情况
                    }
                }
            }
            while(!opt.empty()){ //切记 如果最终操作符栈内还有符号 前面可能push了但还没参与运算
                numAndOptPop(num,opt);
            }
            if(num.peek() == 24){
                System.out.println("Yes");
            }else{
                System.out.println("No");
            }
            num.pop(); //把该行的结果pop掉
        }
    }
    
    public static int toSum(int a, int b, char c){ //根据两个操作数和一个运算符计算
        int sum = 0;
        switch(c){
             case '+' : sum = b+a;break;
             case '-' : sum = b-a;break;
             case 'x' : sum = b*a;break;
             case '/' : sum = b/a;break;
        }
        return sum;
    }
    
    public static int priority(Character a,Character b){
        int pro = 1;
        if(a == 'x' || a == '/'){ //本字符会小于等于栈顶
            pro = 1;
        }else{
            if(b == 'x' || b == '/'){ //本字符优先级大于栈顶(栈顶必定是+或-)
                return -1;
            }
        }
        return pro;
    }
    
    public static void numAndOptPop(Stack<Integer>num, Stack<Character> opt){
        int num1 = num.peek(); num.pop();
        int num2 = num.peek(); num.pop();
        num.push(toSum(num1,num2,opt.peek()));
        opt.pop();
    }
}

法2:

写出式子之后直接对乘除运算进行处理,首先从左到右依次找到x和/符号,然后找到符号前后的数字,将整体(符号前的数+符号+符号后的数)用其运算结果代替,一直到式子中只剩+和-,然后就从左到右加减运算得到最终结果。
import java.util.*;
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        sc.nextLine();
        for(int i=0;i<n;i++) {
            String str = sc.nextLine();
            int j = 0;
            while(str.indexOf("/")!=-1 || str.indexOf("x")!=-1) {        //因为乘除优先级高,所以首先对所有的'x'和'/'进行处理
                if(str.indexOf("/")!=-1 && str.indexOf("x")!=-1)    //乘除都有
                    j = Math.min(str.indexOf("/"),str.indexOf("x"));    //乘除同级别,从左到右顺序计算,谁在前先算谁
                else if(str.indexOf("/")!=-1 && str.indexOf("x")==-1)    //只有除没有乘
                    j = str.indexOf("/");
                else if(str.indexOf("/")==-1 && str.indexOf("x")!=-1)    //只有乘
                    j = str.indexOf("x");
                if(j!=-1) {                                                //在找到一个乘号或者一个除号的时候
                    String tmp1 = "";
                    int k = 1;
                    while(j-k>=0 && str.charAt(j-k)>='0' && str.charAt(j-k)<='9') {        //找到符号前面的数,j-k是为防止检索到-1越界
                        tmp1 = str.charAt(j-k)+tmp1;
                        k++;
                    }
                    String tmp2 = "";
                    k = 1;
                    while(j+k<str.length() && str.charAt(j+k)>='0' && str.charAt(j+k)<='9') {    //找到符号后面的数,j+k是为防止检索到str.length()越界
                        tmp2 += str.charAt(j+k);
                        k++;
                    }
                    //用计算的结果替换原来乘法或者除法的运算
                    if(str.charAt(j)=='/') {
                        String restr = (Integer.parseInt(tmp1) / Integer.parseInt(tmp2))+"";
                        str = str.replaceAll(tmp1+str.charAt(j)+tmp2, restr);
                    }
                    else if(str.charAt(j)=='x') {
                        String restr = (Integer.parseInt(tmp1) * Integer.parseInt(tmp2))+"";
                        str = str.replaceAll(tmp1+str.charAt(j)+tmp2, restr);
                    }
                        
                }
            }
            //在上面的操作完成后剩下得只有加减法运算,优先级同级顺序运算即可。
            int tmp = 0;
            int Sum = 0;
            char f = '+';        //因为Sum=0,第一个操作是Sum一定是加第一个数,所以设符号f为'+'
            for(j=0;j<str.length();j++) {
                if(str.charAt(j)>='0' && str.charAt(j)<='9') {
                    tmp = tmp*10 + (str.charAt(j)-'0');
                }
                else {    //在找到下一个符号的时候完成上一个符号的加减操作然后用新找到符号替换原符号
                    if(f == '+')
                        Sum += tmp;
                    else 
                        Sum -= tmp;
                    f = str.charAt(j);
                    tmp = 0;
                }
                if(j==str.length()-1) {        //Sum +或-最后一个数
                    if(f == '+')
                        Sum += tmp;
                    else 
                        Sum -= tmp;
                }    
            }
            //输出结果
            if(Sum == 24) {
                System.out.println("Yes");
            }
            else
                System.out.println("No");
        }
    }

猜你喜欢

转载自blog.csdn.net/qq_18287147/article/details/106890184
今日推荐