[洛谷P1022]计算器的改良,模拟题,java算法

原题链接

题目描述

ZL 先生首先研究了一些一元一次方程的实例:

  • 4 + 3 x = 8 4+3x=8 4+3x=8
  • 6 a − 5 + 1 = 2 − 2 a 6a-5+1=2-2a 6a5+1=22a
  • − 5 + 12 y = 0 -5+12y=0 5+12y=0

ZL 先生被主管告之,在计算器上键入的一个一元一次方程中,只包含整数、小写字母及 +-= 这三个数学符号(当然,符号“-”既可作减号,也可作负号)。方程中并没有括号,也没有除号,方程中的字母表示未知数。
可认为键入的一元一次方程均为合法的,且有唯一实数解。

输入格式

一个一元一次方程。

输出格式

解方程的结果(精确至小数点后三位)。

样例输入 #1
6a-5+1=2-2a
样例输出 #1
a=0.750
public static void solve() throws IOException {
    List<String> list = new ArrayList<>();

    String s = readString();
    s = "+" + s;//加个符号,例如 2x = 4, 编程 +2x = +4,这样就知道 x的系数为正还是负,最后将 x的系数合并
    s = s.replaceAll("\\+\\+", "+");//排除++的情况
    s = s.replaceAll("\\+\\-", "-");//排除+-的情况
    int idx = s.indexOf('=');
    int sum = help(s, list, idx, 0, 1);//等号左边

    s = s.substring(idx + 1);
    s = "+" + s;
    s = s.replaceAll("\\+\\+", "+");//排除++的情况
    s = s.replaceAll("\\+\\-", "-");//排除+-的情况
    sum = help(s, list, s.length(), sum, -1);//等号右边
    sum = -sum;// 得到相反数,这样可以将已知数放等号右边,将未知数放等号左边如:2x=4

    int sum2 = 0;// 计算未知数的系数
    String a = "";
    for (String t : list) {
        t = t.replaceAll("\\-\\-", "+");
        t = t.replaceAll("\\-\\+", "-");
        t = t.replaceAll("\\+\\+", "+");
        t = t.replaceAll("\\+\\-", "-");
        int idx2 = 0;
        for (int i = 0; i < t.length(); i++) {
            if ((t.charAt(i) < '0' || t.charAt(i) > '9') && t.charAt(i) != '-' && t.charAt(i) != '+') {
                idx2 = i;//得到系数
                break;
            }
        }
        a = t.substring(idx2);//未知字符
        t = t.substring(0, idx2);//系数
        if (t.length() == 1) {//出现 -x或者x的情况系数补充 -1或者1
            t = t + "1";
            sum2 += Integer.valueOf(t.substring(0, idx2 + 1));
            continue;
        }
        sum2 += Integer.valueOf(t.substring(0, idx2));
    }

    double res = (double) (sum) / sum2;
    if (res == 0) res = Math.abs(res);//可能出现-0.000的情况
    printWriter.printf("%s=%.3f", a, res);
}
// idx用于确定枚举边界,sign用于判断字符串s位于等号左边还是右边
public static int help(String s, List<String> list, int idx, int sum, int sign) {
    outer:
    for (int i = 0; i < idx; i++) {
        boolean flag = false;//用于判断是否有未知数,没有未知数的加到 sum中,有未知数的放到 list集合中
        for (int j = i + 1; j < idx; j++) {//枚举到下一个加减号
            char ch = s.charAt(j);
            if (ch != '+' && ch != '-' && (ch < '0' || ch > '9')) flag = true;//出现了未知字符
            if (ch == '+' || ch == '-') {//遇到了下一个加减号
                if (!flag) {//未出现未知数
                    sum += Integer.valueOf(s.substring(i, j)) * sign;
                } else {
                    if (sign == 1) {//等号左边
                        list.add(s.substring(i, j));
                    } else {//等号右边
                        list.add("-" + s.substring(i, j));
                    }
                }
                i = j - 1; break;//从正负号开始枚举
            }
            if (j == idx - 1) {//最后一个由正负号组成的数字
                if (!flag) {
                    sum += Integer.valueOf(s.substring(i, idx)) * sign;
                } else {
                    if (sign == 1) {
                        list.add(s.substring(i, idx));
                    } else {
                        list.add("-" + s.substring(i, idx));
                    }
                }
                break outer;
            }
        }
    }
    return sum;
}

好像没什么考点,纯模拟,注意一下正负号,以及未知数的系数为一或者负一的特殊情况,还有就是等号式子开头可能自带正号或者不带符号,遇到这种情况可以再加一个正号,然后通过replaceAll()方法变为只有一个正号

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值