NOIP2000普及组 T1计算器的改良

时间:2025-02-12 18:37:02

主要考字符串处理,把等式从等号中间断开,左边的区域为left,右边的区域为right。

开四个数组分别用来存储区域left和right中未知数的系数,区域left和right中的常数

先处理区域left,把区域left中含有未知数的数字和常数分别存储进数组,再处理区域right(字符串处理这里省略)

最后把存储区域left和right的未知数系数和常数的数组分别化简(合并同类项),进行平时解方程时候的模拟就好了。

主要看代码理解吧,思路讲的有点抽象了。

 var
l_unk,r_unk,l_num,r_num:array[..] of longint; //上面所说的四个数组
top1 ,top2 ,top3 ,top4 :longint; //四个数组的栈顶
s,str:string;
i,j:longint;
unk:char; //未知数的符号
mid,last,value:longint;
begin
readln(s);
for i:= to length(s) do //处理区域left
begin
if s[i] in ['a'..'z'] then unk:=s[i]; //找出未知数
if s[i]='=' then mid:=i; //找出等式中间位置
end;
if s[length(s)]<>unk then
s:=s+'+';
last:=;
for i:= to mid do
begin
if s[i]=unk then //如果遇到未知数
begin
str:=copy(s,last,i-last); //字符串处理
val(str,value); //字符串转数字
inc(top1);
l_unk[top1]:=value; //进栈
last:=i+;
end;
if (not(s[i] in [''..''])) and (s[i]<>unk) and (i<>last) then //如果遇到了常数
begin
str:=copy(s,last,i-last); //字符串处理
val(str,value); //转数字
inc(top3);
l_num[top3]:=value; //进栈
last:=i;
end;
end;
last:=mid+;
for i:=mid+ to length(s) do //处理区域right
begin
if s[i]=unk then // 同上
begin
str:=copy(s,last,i-last);
val(str,value);
inc(top2);
r_unk[top2]:=value;
last:=i+;
end;
if (not(s[i] in [''..''])) and (s[i]<>unk) and (i<>last) then
begin
str:=copy(s,last,i-last);
val(str,value);
inc(top4);
r_num[top4]:=value;
last:=i;
end;
end;
for i:=top1- downto do l_unk[i]:=l_unk[i]+l_unk[i+]; //化简数组,合并同类项
for i:=top2- downto do r_unk[i]:=r_unk[i]+r_unk[i+];
for i:=top3- downto do l_num[i]:=l_num[i]+l_num[i+];
for i:=top4- downto do r_num[i]:=r_num[i]+r_num[i+];
l_unk[]:=l_unk[]-r_unk[]; //解方程,左边未知数系数加上右边未知数的系数的相反数
r_num[]:=r_num[]-l_num[]; //解方程,右边常数加上左边常数的相反数
writeln(unk,'=',r_num[]/l_unk[]::); //输出保留3位小数
end.