无限

[题解]洛谷P1022:计算器的改良
原题链接:P1022 计算器的改良题目信息请自行至原题链接处查看,以下将默认读者已对题目大致意思有了解并有一定C+...
扫描右侧二维码阅读全文
30
2018/11

[题解]洛谷P1022:计算器的改良

原题链接:P1022 计算器的改良


题目信息请自行至原题链接处查看,以下将默认读者已对题目大致意思有了解并有一定C++算法竞赛基础。

本题整体上非常简单,属于非常水的入门题目,难点主要在于对输入数据的解析,对于这种复杂字符串,我们可以采用getchar()处理,这一方法的好处在于灵活性大,不受格式限制,解析自由;相对地,它也具有编程较为困难,不利于处理整体,对思维考验较大等缺陷。

考虑对输入方程的解析,首先大致规划出几种模式:


模式及附加样例:

  • 常规:2x=1
  • 未知数系数省略:x+1=5 6-x=3
  • 两边均存在未知数:5a+13=3a-2
  • 鬼畜的多个未合并化简项:8q+1-1+1-1+1-1+1-1+1-1-6q=-4q+8-3
  • 等号后紧跟着负号:在上一example中有体现

附输出结果:

  • x=0.500
  • x=4.000 x=3.000
  • a=-7.500
  • q=0.833

显得特别复杂。

这时就可以体现getchar()的优势了,化繁为简,分别用变量标记当前项的正负、运算正处在左方还是右方,读入到非数字字符时完成对总最简系数的计算即可。至于对未知数的读入和判定则更为简单,注意细节即可。

特别强调数字的读入。考虑83这个数字,首先用getchar()读取到字符8,下一次循环时将读入字符3,则临时结果tmp_num的值第一次应为8,第二次为83,不难得出tmp_num=tmp_num*10+numtmp_num初始化为0)的结论,其中num=c-'0'一定要注意,字符与数字是不同的,减去字符0才能得到正确的数字结果(想一想,为什么?)。

根据以上的全部分析,结合自己的思考,并注意编写的细节,可以通过全部6个测试点中的5个。算法本身已经没有任何问题(此处指在题目的条件下,若系数过大还需使用高精),但需要注意C/C++语言double类型的一个特性:

零除以负数等于负零。

这样,我们就能够得到本题的AC代码了。


题解:(R14164281

#include<bits/stdc++.h>
using namespace std;
int main(){
    int c=getchar();
    int tmp_num=0;
    char x_flag='~';
    bool sign_flag=true;//true<=>(+);false<=>(-)
    bool lr_flag=false;//false<=>left;true<=>right
    bool end_input=false;
    int a=0,b=0;//ax+b=0
    do{
        if(isdigit(c)){//数字后的处理
            end_input=false;
            tmp_num=tmp_num*10+(c-'0');
        }else if(c=='+'){//运算符号:加
            if(end_input==false)b+=lr_flag?(sign_flag?-tmp_num:tmp_num):(sign_flag?tmp_num:-tmp_num);
            sign_flag=true;
            tmp_num=0;
        }else if(c=='-'){//运算符号:减
            if(end_input==false)b+=lr_flag?(sign_flag?-tmp_num:tmp_num):(sign_flag?tmp_num:-tmp_num);
            sign_flag=false;
            tmp_num=0;
        }else if(c=='='){//左右变化标记:等号
            if(end_input==false)b+=sign_flag?tmp_num:-tmp_num;
            lr_flag=true;
            tmp_num=0;
            sign_flag=true;
        }else{//未知数后的操作
            if(x_flag=='~')x_flag=(char)c;
            a+=lr_flag?(sign_flag?-tmp_num:tmp_num):(sign_flag?tmp_num:-tmp_num);
            if(!tmp_num)a+=lr_flag?(sign_flag?-1:1):(sign_flag?1:-1);
            end_input=true;
            tmp_num=0;
        }
        c=getchar();
    }while(c!=EOF&&c!='\n'&&c!='\r');
    if(end_input==false)b+=sign_flag?-tmp_num:tmp_num;
    //全部化为ax+b=0的形式
    //原方程的解即为x=-b/a
    double ans1=-b;
    double ans2=a;
    double ans=ans1/ans2;
    if(a==0||b==0)ans=0;//特判等于0的情况防止除零错以及负零,若题目要求无解输出特定字符串还可修改条件后在这里输出
    printf("%c=%.3f",x_flag,ans);
    return 0;
}
最后修改:2019 年 01 月 26 日 04 : 18 PM

发表评论