[NOIP2000 普及组] 计算器的改良
题目背景
NCL 是一家专门从事计算器改良与升级的实验室,最近该实验室收到了某公司所委托的一个任务:需要在该公司某型号的计算器上加上解一元一次方程的功能。实验室将这个任务交给了一个刚进入的新手 ZL 先生。
题目描述
为了很好的完成这个任务,ZL 先生首先研究了一些一元一次方程的实例:
- \(4+3x=8\)。
- \(6a-5+1=2-2a\)。
- \(-5+12y=0\)。
ZL 先生被主管告之,在计算器上键入的一个一元一次方程中,只包含整数、小写字母及 +
、-
、=
这三个数学符号(当然,符号“-
”既可作减号,也可作负号)。方程中并没有括号,也没有除号,方程中的字母表示未知数。
你可假设对键入的方程的正确性的判断是由另一个程序员在做,或者说可认为键入的一元一次方程均为合法的,且有唯一实数解。
输入格式
一个一元一次方程。
输出格式
解方程的结果(精确至小数点后三位)。
样例 #1
样例输入 #1
6a-5+1=2-2a
样例输出 #1
a=0.750
我的解答
我是很纯粹的模拟,感觉麻烦死了,看了大佬的做法感觉自愧不如,还有很多东西要学习。另外在这题中需要注意在浮点数中是有-0.0的,因此要注意将-0以0的形式输出
#include <iostream>
#include <string>
#include <vector>
#include <regex>
using namespace std;
vector<string> left_num,right_num;
string equation;
regex r("-?([0-9]+)"),r1("-?([a-z])");
char a;
const float eps=0.0000001;
void get_half_equation(string str, vector<string>& v)
{
int i=0;
while(i<str.size())
{
if(str[i]=='+')i++;
else
{
for(int j=1;j<=str.size()-i;j++)
{
if(str[i+j]=='+'||str[i+j]=='-'||i+j==str.size())
{
string temp = str.substr(i,j);
if(regex_match(temp,r1))
temp.insert(temp.size()-1,"1");
v.push_back(temp);
i+=j;
break;
}
}
}
}
}
void classify()
{
vector<string> temp1;
vector<string> temp2;
for(string num:left_num)
{
if(regex_match(num,r))
{
if(num[0]=='-')temp2.push_back(num.substr(1));
else temp2.push_back("-"+num);
}
else
{
a=num.back();
temp1.push_back(num.substr(0,num.size()-1));
}
}
for(string num:right_num)
{
if(regex_match(num,r))
temp2.push_back(num);
else
{
if(num[0]=='-')
num=num.substr(1);
else
num="-"+num;
a=num.back();
temp1.push_back(num.substr(0,num.size()-1));
}
}
left_num=temp1;
right_num=temp2;
}
float add_num(vector<string> nums)
{
int ans=0;
bool is_negative=false;
for(string num:nums)
{
if(num[0]=='-')ans+=(-1*stoi(num.substr(1)));
else ans+=stoi(num);
}
return ans;
}
int main()
{
cin>>equation;
int x=equation.find('=');
get_half_equation(equation.substr(0,x),left_num);
get_half_equation(equation.substr(x+1),right_num);
classify();
float ans = add_num(right_num)/add_num(left_num);
ans=(ans<eps&&ans>-eps)?0.0:ans;
printf("%c=%.3f",a,ans);
return 0;
}
第二次优化版本,和上一种做法的本质区别就是直接统计未知数域的值和实数域的值,并以等号为界限,通过乘-1来实现移项操作
#include <iostream>
#include <string>
#include <regex>
using namespace std;
const float eps=0.00001;
regex r("-?([0-9]+)");
string equation;
int main()
{
cin>>equation;
int i=0,flag=1,k=0,b=0;
char x;
while(i<equation.size())
{
if(equation[i]=='+')i++;
else if(equation[i]=='=')
{
i++;
flag=-1;
}
else
{
for(int j=1;j+i<=equation.size();j++)
{
if(equation[i+j]=='-'||equation[i+j]=='+'||equation[i+j]=='='||i+j==equation.size())
{
int is_negative=1;
string temp=equation.substr(i,j);
if(temp[0]=='-')
{
is_negative=-1;
temp=temp.substr(1);
}
if(regex_match(temp,r))
k+=stoi(temp)*is_negative*flag;
else
{
x=temp.back();
if(temp.size()==1)
b+=1*is_negative*flag;
else
b+=stoi(temp.substr(0,temp.size()-1))*is_negative*flag;
}
if(i+j==equation.size()-1)i=equation.size();
i+=j;
break;
}
}
}
}
float ans=k/(b*-1.0);
ans=(ans<eps&&ans>-eps)?0:ans;
printf("%c=%.3f",x,ans);
return 0;
}
标签:NOIP2000,改良,equation,计算器,back,substr,num,ans,include
From: https://www.cnblogs.com/jyhlearning/p/16716634.html