jzoj2563 区间运算

又是万恶的表达式解析.

这里写图片描述

用了黑科技:
首先用栈把括号给去掉,把区间给提取出来单独存然后用’$’ 代替

处理的时候就可以根据这是第几个’$’来处理,
其他数也是等价的

程序打了一个小时,不过我自己认为打的还是挺优美的.

DEMO

type
    str_=string;
    sec=record
        l,r:double;
    end;
var
    ex:str_;
    i,j,k:longint;
    tmp:sec;
    no0:boolean;
function max(a,b:double):double;
begin
    if(a>b) then exit(a) else exit(b);
end;
function min(a,b:double):double;
begin
    if(a>b) then exit(b) else exit(a);
end;

function copy0(ex:str_; be,ed:longint):str_;
begin
    exit(copy(ex,be,ed-be+1));
end;
function pos0(ex:str_;be:longint;target:char):longint;
var i:longint;
begin
    for i:=be to length(ex) do
        if ex[i]=target then exit(i);
    exit(0);
end;
function lastchar(str:str_; loc:longint):char;
var j:longint;
begin
    for j:=loc-1 downto 1 do if (str[j]<>'#') then exit(str[j]);
end;

//格式: 数1,数2
function toSec(ex:str_):sec;
var i:longint;
    rs:sec;
begin
    for i:=1 to length(ex) do
        if (ex[i]=',') then
        begin
            val(copy(ex,1,i-1),rs.l);
            val(copy(ex,i+1,length(ex)),rs.r);
            exit(rs);
        end;
end;
function toString(x:sec):str_;
var s1,s2:str_;
begin
    str(x.l,s1);
    str(x.r,s2);
    exit('['+s1+','+s2+']');
end;

procedure not0(var x:sec);
var
    l,r:double;
begin
    l:=min(-x.l,-x.r);
    r:=max(-x.l,-x.r);
    x.l:=l;
    x.r:=r;
end;
function mul(a,b:sec):sec;
var
    rs:sec;
begin
    rs.l:=min(a.l*b.l,min(a.l*b.r,min(a.r*b.l,a.r*b.r)));
    rs.r:=max(a.l*b.l,max(a.l*b.r,max(a.r*b.l,a.r*b.r)));
    exit(rs);
end;
function divi(a,b:sec):sec;
var
    rs:sec;
begin
    if (b.l<=0)and(b.r>=0) then
    begin
        no0:=true;
        exit(a);
    end;
    rs.l:=min(a.l/b.l,min(a.l/b.r,min(a.r/b.l,a.r/b.r)));
    rs.r:=max(a.l/b.l,max(a.l/b.r,max(a.r/b.l,a.r/b.r)));
    exit(rs);
end;
function add(a,b:sec):sec;
var
    rs:sec;
begin
    rs.l:=min(a.l+b.l,min(a.l+b.r,min(a.r+b.l,a.r+b.r)));
    rs.r:=max(a.l+b.l,max(a.l+b.r,max(a.r+b.l,a.r+b.r)));
    exit(rs);
end;
function minus(a,b:sec):sec;
var
    rs:sec;
begin
    rs.l:=min(a.l-b.l,min(a.l-b.r,min(a.r-b.l,a.r-b.r)));
    rs.r:=max(a.l-b.l,max(a.l-b.r,max(a.r-b.l,a.r-b.r)));
    exit(rs);
end;
function decode(ex:str_):sec;
var
    st:array[0..100] of sec;
    //stack:array[0..100] of char;
    bloc,th,stot,top:longint;
    isnotsec,last,k,j,i:longint;
    loc:array[0..100] of longint;
    pre,suf,stack,tmpp:str_;
    tmp,rs,part:sec;
begin
    rs.l:=0;
    rs.r:=0;
    if (no0) then exit(rs);
    stack:='000000000000000000000000000000000000000000000';
    //fillchar(stack,sizeof(stack),0);
    fillchar(st,sizeof(st),0);
    top:=0; stot:=0;
    i:=1;
    //解析括号与区间
    while (i<=length(ex)) do
    begin
        if (ex[i]=')') then
        begin
            tmpp:='';
            for j:=top downto 1 do
            begin
                dec(top);
                if (stack[j]='(') then
                begin
                    bloc:=loc[j];
                    break;
                end;
                if (stack[j]='$') then dec(stot);
            end;
            tmp:=decode(copy0(ex,bloc+1,i-1));
            pre:=copy0(ex,1,bloc-1)+toString(tmp);
            suf:=copy0(ex,i+1,length(ex));
            i:=length(pre);
            ex:=pre+suf;

            inc(top);
            stack[top]:='$';
            inc(stot);
            st[stot]:=tmp;
        end else
        if (ex[i]='[') then
        begin
            k:=pos0(ex,i,']');
            inc(stot);
            st[stot]:=toSec(copy0(ex,i+1,k-1));
            inc(top);
            stack[top]:='$';
            loc[top]:=i;
            i:=k;
        end else
        begin
            inc(top);
            stack[top]:=ex[i];
            loc[top]:=i;
        end;
        inc(i);
    end;
    //取反
    th:=0;
    for i:=1 to top do
    begin
        if (stack[i]='$') then inc(th);
        if (stack[i]='-') then
        begin
            if(stack[i+1]='$')and(stack[i-1]<>'$') then
            begin
                not0(st[th+1]);
                stack[i]:='#';
            end;
        end;
    end;
    //乘除 加减
    part.l:=-maxlongint;
    part.r:=0;
    th:=0;
    last:=1;
    for i:=1 to top do
    begin
        if (stack[i]='#') then continue;
        if (stack[i]='$') then
        begin
            stack[i]:='#';
            inc(th);
            if (part.l=-maxlongint) then part:=st[th] else
            begin
                if (lastchar(stack,i)='*') then
                    part:=mul(part,st[th]);
                if (lastchar(stack,i)='/') then
                    part:=divi(part,st[th]);
                stack[i-1]:='#';
            end;
        end;
        if (stack[i]='+')or(stack[i]='-') then
        begin
            if (last=1) then rs:=add(rs,part) else rs:=minus(rs,part);
            if (stack[i]='+') then last:=1 else last:=-1;
            part.l:=-maxlongint;
            part.r:=0;
        end;
    end;
    if (last=1)and(part.l<>-maxlongint) then rs:=add(rs,part) else rs:=minus(rs,part);
    exit(rs);
end;

begin
    assign(input,'2563.in');  reset(input);
    while (not eof) do
    begin
        no0:=false;
        readln(ex);
        tmp:=decode(ex);
        if (no0=false) then writeln('[',tmp.l:0:3,',',tmp.r:0:3,']')
        else
            writeln('Division by zero');
    end;
end.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值