UVA 1661 Equation (后缀表达式,表达式树,模拟,实现)

题意:给出一个后缀表达式f(x),最多出现一次x,解方程f(x) = 0。

读取的时候用一个栈保存之前的结点,可以得到一颗二叉树,标记出现'X'的路径,先把没有出现'X'的子树算完,由于读取建树的时候是由底向上的,

这步可以在读取的时候顺带完成。

注意'X'或'1/x'在某个结点和'0'相乘,那么'X'等效与没有出现过,把之后的结点标记为常数。

然后dfs模拟运算和移项。

还有一些输入输出的小细节和几组测试数据,具体看代码。

WA了很多发,去找数据手动对拍好久终于发现(1/(1/x))=0这种情况是被当作无解。。。而我当作x = 0来处理了,QAQ。为何解个一元一次如此艰辛。。。

第一次写5000B+,模拟真的很难写有没有。手写一个分数的模板

#include<bits/stdc++.h>
using namespace std;

const int maxn = 666;
typedef long long ll;

ll gcd(ll a,ll b) { return b?gcd(b,a%b):a; }

struct Fra
{
    ll p,q;
    Fra(ll x = 0,ll y = 1):p(x),q(y){ normal(p,q); }
    void normal(ll &p,ll &q) { ll g = gcd(p,q); p/=g; q/=g; }
    Fra operator = (int x) {  p = x; q = 1; return *this; }
    Fra operator = (ll x) { p = x; q = 1; return *this; }
    Fra operator - () { return {-p,q}; }
    Fra operator + (Fra &r) {
        ll m,n;
        m = p*r.q+r.p*q;
        n = q*r.q;
        normal(m,n);
        return {m,n};
    }
    Fra operator += (Fra& r) { return *this = *this+r; }
    Fra operator - (Fra &r) { return (-r) + *this; }
    Fra operator -= (Fra &r) { return *this = *this-r; }
    Fra operator * (Fra &r) {
        ll m,n;
        m = p*r.p;
        n = q*r.q;
        normal(m,n);
        return {m,n};
    }
    Fra operator *= (Fra &r) { return (*this) = (*this)*r; }
    Fra operator /(Fra &r) { return Fra(r.q,r.p) * (*this); }
    Fra operator /=(Fra &r) { return (*this) = (*this)/r; }
    bool operator == (const Fra& r) const { return p*r.q == r.p*q; }
    bool operator < (Fra& r) { return  p*r.q < r.p*q; }
    void print() { normal(p,q); if(q<0)q = -q,p = -p; printf("%lld/%lld\n",p,q); }
};


struct Node
{
    Node* l,*r;
    Fra f; char op;
    bool fx;
    Node(){};
    Node(Fra &v,Node*a = NULL, Node*b = NULL):f(v),l(a),r(b){};

}nd[maxn];

bool isOp[256];
char rev[256];

Fra cal(Fra &x,Fra &y,char op)
{
    //assert(isOp[op] == true)
    switch(op){
        case '+':return x+y;
        case '-': return x-y;
        case '*': return x*y;
        case '/': return x/y;
    }
    return {233,1};
}

Fra ans;

void calRev(Fra &x,char op)
{
    switch(op){
        case'+':ans-=x; return;
        case'*':ans/=x; return ;
        case'-':ans = x-ans; return;
        case'/':ans = x/ans; return;
    }
}

//之前要预处理
bool dfs(Node* u)
{
    //*u;
    if(u->l == NULL) return true;
    //assert(u.r)
    if(u->l->fx){
        ans = cal(ans,u->r->f,rev[u->op]); //乘以0的情况已经预处理了
        if(!dfs(u->l)) return false;
    }else if(u->r->fx) {
        calRev(u->l->f,u->op);//移项,ans本身可能会是0
        if(ans.q == 0) { return false; }
        if(!dfs(u->r)) return false;
    }
    return true;
}

Node* read(char ch)
{
    int cnt = 0;
        stack<Node*> stk;
        do{
            while(ch == ' ')ch = getchar();
            Node &cur = nd[cnt];
            if(isOp[ch]){
                cur.op = ch;
                cur.r = stk.top(); stk.pop();
                cur.l = stk.top(); stk.pop();
                cur.fx = cur.l->fx || cur.r->fx;
                if(cur.fx){ //系数为0的处理
                    if((cur.op == '*' && (cur.r->fx ? cur.l->f == 0 : cur.r->f == 0))
                    || (cur.op == '/' && cur.r->fx && cur.l->f == 0) ) {
                        cur.fx = false;
                        cur.f = 0; cur.l = cur.r = NULL;
                    }
                }else { //预处理,边读边算
                    cur.f = cal(cur.l->f,cur.r->f,cur.op);
                    cur.l = cur.r = NULL;
                }
            }else {
                if(ch == 'X'){
                    cur.fx = true;
                }else {
                    cur.fx = false;
                    int data = ch-'0';
                    while(ch = getchar(), ch>='0'&&ch<='9') data = data*10+ch-'0';
                    cur.f = data;
                }
                cur.l = cur.r = NULL;
            }
            stk.push(nd+cnt);
            ch = getchar(); cnt++;
        }while(ch != '\n'&&~ch);
    return stk.top();
}

int main()
{
    //freopen("in.txt","r",stdin);
    isOp['+'] = isOp['-'] = isOp['*'] = isOp['/'] = true;
    rev['+'] = '-'; rev['-'] = '+'; rev['*'] = '/'; rev['/'] = '*';
    char head;
    while(~(head = getchar())){
        Node* root = read(head);
        if(!root->fx) {
            if(root->f == 0) puts("MULTIPLE");
            else puts("NONE");
            continue;
        }
        ans = 0;
        if(dfs(root)){ printf("X = "); ans.print(); }
        else {puts("NONE"); continue; }
    }
    return 0;
}

/*
1 1 X / /
1 1 X 2 - / /


1 X /
0 X * 1 +
0 X / 1 +

9 9 9 9 9 9 9 9 9 9 9 9 9 X 1 * * * * * * * * * * * * * +
7 6 - 8 / 8 2 * / 0 3 - + 5 5 1 / + 1 X 2 + + 8 8 + + * +
7 8 X + * 1 8 5 7 3 + * * 7 6 6 / 3 + + 6 5 7 / - * / / +
*/

 

posted @ 2015-08-29 14:50  陈瑞宇  阅读(680)  评论(2编辑  收藏  举报