一、题目链接

  http://codeforces.com/gym/100198/problem/G

二、题意

  看样例就能明白,写表达式解析器。

三 、思路

  一看这题目,立马就会想到“后缀表达式”,考虑到这里有变量,在把中缀表达式变为后缀表达式时,把变量替换成常量即可。注意,define 2 3 表示,下面的2用3来替换。和C语言是一样的。

PS:然而,我用Java写的,总是RE在第四个样例,实在找不到哪里抛异常了。各位同行,如果您能找到我的代码的bug,烦请您在评论区留下出bug的样例。谢谢!

四、源代码

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import java.util.Stack;

public class Main {
    static final String digitPattern = "-?\\d+";
    static final File fin = new File("plcool.in");
    static final File fout = new File("plcool.out");
    static String input;
    static ArrayList<String> inExp = new ArrayList<String>();
    static ArrayList<String> postExp = new ArrayList<String>();
    static Map<Character, Integer> prior = new HashMap<Character, Integer>();
    static Map<String, String> define = new HashMap<String, String>();
    static InputStream is = null;
    static PrintStream ps = null;
    static {
        prior.put('^', 3);
        prior.put('*', 2);
        prior.put('/', 2);
        prior.put('%', 2);
        prior.put('+', 1);
        prior.put('-', 1);
        prior.put('(', 0);
        prior.put(')', 0);
    }

    static String findRoot(String key) {
        if(!define.containsKey(key))return key;
        else return findRoot(define.get(key));
    }

    static int power(int x, int y) {
        int res = 1;
        while(y > 0) {
            if((y & 1) == 1)res *= x;
            x = x * x;
            y >>= 1;
        }
        return res;
    }

    static int mod(int x, int y) {
        int sign = ((x >>> 31) ^ (y >>> 31)) == 0 ? 1 : -1;
        return (Math.abs(x) % Math.abs(y)) * sign;
    }

    static void split() {
        inExp.clear();
        int s = 0, t = 0, len = input.length();
        boolean befOper = false;
        for (int i = 0; i < len; ++i) {
            if(Character.isDigit(input.charAt(i)) || (input.charAt(i) == '-' && (befOper || i == 0))) {
                for(s = i++;i < len && Character.isDigit(input.charAt(i)); ++i);
                inExp.add(input.substring(s, i));
                --i;
                befOper = false;
            }
            else if(Character.isLetter(input.charAt(i))) {
                for(s = i;i < len && (Character.isLetter(input.charAt(i))
                        || Character.isDigit(input.charAt(i))); ++i);
                inExp.add(input.substring(s, i));
                --i;
            }
            else if(prior.containsKey(input.charAt(i))) {
                inExp.add(input.charAt(i) + "");
                befOper = true;
            }
        }
        //inExp.forEach(e -> ps.print(e + " "));
        for (int i = 0, sz = inExp.size(); i < sz; ++i) {
            String now = inExp.get(i);
            if (define.containsKey(now)) {
                String root = findRoot(now);
                if(!root.matches(digitPattern))root = "0";
                inExp.set(i, root);
            }
            else if(!prior.containsKey(now.charAt(0)) && !now.matches(digitPattern))inExp.set(i, "0");
        }
        //inExp.forEach(e -> ps.print(e + " "));
    }

    static Stack<Character> opers = new Stack<Character>();
    static void toPost() {
        opers.clear();
        postExp.clear();
        for (String s : inExp) {
            if (s.matches(digitPattern))
                postExp.add(s);
            else {
                if (opers.isEmpty())
                    opers.push(s.charAt(0));
                else {
                    char top = opers.peek();
                    char c = s.charAt(0);
                    if (s.equals(")")){
                        while (!opers.isEmpty() && opers.peek() != '(') {
                            postExp.add(opers.pop() + "");
                        }
                        if (!opers.isEmpty() && opers.peek() == '(')
                            opers.pop();
                    }
                    else if((c != '(' && c != '^' && prior.get(c) <= prior.get(top))){
                        for(top = opers.peek();prior.get(c) <= prior.get(top);) {
                            postExp.add(opers.pop() + "");
                            if(!opers.isEmpty())top = opers.peek();
                            else break;
                        }
                        opers.push(c);
                    }
                    else
                        opers.push(c);
                }
            }
        }
        while(!opers.isEmpty()) {
            char c = opers.pop();
            if(c == ')')continue;
            else postExp.add(c + "");
        }
        //postExp.forEach(e -> ps.print(e + " "));
    }

    static Stack<Integer> digits = new Stack<Integer>();
    static int calcResult() {
        digits.clear();
        for(String s : postExp) {
            if(s.matches(digitPattern))digits.push(Integer.parseInt(s));
            else {
                char c = s.charAt(0);
                int last1 = digits.pop(), last2 = digits.pop();
                switch (c) {
                case '-':{
                    digits.push(last2 - last1);
                    break;
                }
                case '+':{
                    digits.push(last2 + last1);
                    break;
                }
                case '*':{
                    digits.push(last2 * last1);
                    break;
                }
                case '/':{
                    digits.push(last2 / last1);
                    break;
                }
                case '%':{
                    digits.push(mod(last2, last1));
                    break;
                }
                case '^':{
                    digits.push(power(last2, last1));
                    break;
                }
                }
            }
        }
        return digits.pop();
    }

    static String[] parts;
    public static void main(String[] args) throws Exception {
//        is = new FileInputStream(fin);
//        ps = new PrintStream(new FileOutputStream(fout));
        is = System.in;
        ps = System.out;
        Scanner scanner = new Scanner(is);
        while (scanner.hasNextLine()) {
            input = scanner.nextLine().trim().toLowerCase();
            if (input.charAt(0) == 'p') {
                input = input.replaceAll(" ", "");
                input = input.substring(5);
                split();
                toPost();
                int res = calcResult();
                ps.println(res);
            }

            else {
                parts = input.split(" ");
                if (define.containsKey(parts[1]))
                    continue;
                else {
                    String root1 = findRoot(parts[1]);
                    String root2 = findRoot(parts[2]);
                    if(!root1.equals(root2))define.put(parts[1], parts[2]);
                }
            }
        }
        scanner.close();
    }
}

CFGym 100198G 题解的更多相关文章

  1. CFGym 101490J 题解

    一.题目链接 http://codeforces.com/gym/101490 二.题面 三.题意 给你n个点,代表学生所在位置,n个点,代表老师所在位置.每个学生分配一个老师.让你找出一个最小的学生 ...

  2. CFGym 101490E 题解

    一.题目链接 http://codeforces.com/gym/101490 二.题面 三.题意 给你一个图,n个点,m条边,一个x,从顶点1走到顶点n.假设从顶点1走到顶点n的最短路为d,x代表你 ...

  3. CFGym 101161I 题解

    一.题目链接 http://codeforces.com/gym/101161/problem/I 二.题意 给定一棵树,一个初始的省会城市,若干个询问,0表示修改省会城市,1表示查询去省会必须经过指 ...

  4. CFGym 101194L 题解

    一.题目链接 http://codeforces.com/gym/101194/problem/L 二.题意 有4个队伍,要打6场比赛(刚好每两个队伍都能相互比一次),若A和B比赛有3种结果: A赢B ...

  5. CFGym 101194D 题解

    一.题目链接 http://codeforces.com/gym/101194/problem/D 二.题意 给定一个数字n和一个数字k,一个n个整数的序列,让你在里面找尽可能多的长度为k的符合“要求 ...

  6. CFGym 101505I 题解

    一.题目链接 http://codeforces.com/gym/101505 二.题意 这题其实主要就是题意,理解题意后,就是水题了.我想了下,主要原因就是这几点: 1.题意太过英文化,很多句子不能 ...

  7. CFGym 100211J 题解

    一.题目 二.题意 给定一个字母表(最多也就是英文小写字母的前10个字母),一个交换表,两个字符串,判断字符串A能否通过交换表的交换方式变成字符串B. 三.思路 1.一开始,比赛时,我半模拟半记忆化地 ...

  8. [CF-GYM]Abu Tahun Mod problem题解

    前言 这道题比较简单,但我还是想了好一会 题意简述 Abu Tahun很喜欢回文. 一个数组若是回文的,那么它从前往后读和从后往前读都是一样的,比如数组\(\left\{1\right\},\left ...

  9. 2016 华南师大ACM校赛 SCNUCPC 非官方题解

    我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...

随机推荐

  1. Mac OS 下安装 Vagrant

    Vagrant是一款用来构建虚拟开发环境的工具,它其实算是一个跨平台的虚拟机管理工具 1 安装 1.1 安装Vagrant 下载好pkg文件后,下一步安装即可 1.2 安装Virtualbox Vag ...

  2. vue 脚手架(二,项目依赖说明 package.json)

    本文以转移至本人的个人博客,请多多关注! 本文以转移至本人的个人博客,请多多关注! 本文以转移至本人的个人博客,请多多关注! 本文以转移至本人的个人博客,请多多关注! 继续上一篇, 上一篇讲了 vue ...

  3. Andrew and Taxi CodeForces - 1100E (思维,拓扑)

    大意: 给定有向图, 每条边有一个权值, 假设你有$x$个控制器, 那么可以将所有权值不超过$x$的边翻转, 求最少的控制器数, 使得翻转后图无环 先二分转为判定问题. 每次check删除能动的边, ...

  4. torch中的多线程threads学习

    torch中的多线程threads学习 torch threads threads 包介绍 threads package的优势点: 程序中线程可以随时创建 Jobs被以回调函数的形式提交给线程系统, ...

  5. POJ-3744-概率dp+矩阵幂(分段)

    Scout YYF I Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 10214   Accepted: 2980 Desc ...

  6. 008PHP文件处理——文件操作r w (用的比较多) a x(用的比较少) 模式 rewind 指针归位:

    <?php /** *文件操作r w (用的比较多) a x(用的比较少) 模式 rewind 指针归位: */ /*$a=fopen('a.txt','r'); echo fread($a,f ...

  7. HDU1102 最小生成树prim算法

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1102 题意:给出任意两个城市之间建一条路的时间,给出哪些城市之间已经建好,问最少还要多少时间使所有的城 ...

  8. Eclipse Oxygen SVN Connector Setup

    新版的Eclipse(Oxygen)安装完Subversive后,现时无法自动安装SVN Connector,无论选择哪个都会自动关闭. 解决方法: Help -> Install New So ...

  9. 让IE兼容console——“由于出现错误80020101而导致此项操作无法完成”的解决方案

    问题描述 经测试发现问题只出现在: 1.原生IE8(其他版本IE模拟出的IE8无此问题) 2.从打开IE8没有开启过F12(曾经开启过又关闭的无此问题) IE8报错“由于出现错误80020101而导致 ...

  10. 经典排序方法 python

    数据的排序是在解决实际问题时经常用到的步骤,也是数据结构的考点之一,下面介绍10种经典的排序方法. 首先,排序方法可以大体分为插入排序.选择排序.交换排序.归并排序和桶排序四大类,其中,插入排序又分为 ...