计算24点

#include <iostream>
#include <string>
#include <sstream>
#include <cmath>
using namespace std;

class C24p
{
private:
    struct Cell{
        union{
            double dbl;
            char   sig; //1+2-3*4/
        }num;
        char typ;       //0数值1符号
        int  id;
        Cell* left;
        Cell* right;
        Cell():left(NULL),right(NULL){}
    }exp[7],ele[8];
    char exitflag;
    ostringstream  out;

    void putele(int n);
    bool chkele(int n);
    bool cal();
    void show();
    void toformulate(C24p::Cell* root);
    char sigprio(const C24p::Cell &val); //符号优先级
public:
    C24p(double num1=1,double num2=1,double num3=1,double num4=1);
    const string getstr() const;
    void run();
};

C24p::C24p(double num1,double num2,double num3,double num4)
{
    int i;
    ele[0].num.dbl=num1;
    ele[1].num.dbl=num2;
    ele[2].num.dbl=num3;
    ele[3].num.dbl=num4;
    for(i=0;i<4;++i){
        ele[i].typ=0;   //数值
        ele[i+4].typ=1; //符号
        ele[i+4].num.sig=i+1;
    }
    for(i=0;i<8;++i){
        ele[i].id=i;
    }
    exitflag=0;
}

void C24p::putele(int n)
{
    int start,end;

    start=0;
    if(n<2){
        end=4;
    }
    else{
        end=8;
    }
    for(int i=start;i<end;++i){
        exp[n]=ele[i];
        if(chkele(n)){
            putele(n+1);
        }
        if(exitflag==1){
            break;
        }
    }
}

bool C24p::chkele(int n)
{
    int i;
    int nums=0,sigs=0;

    for(i=0;i<=n;++i){
        if(exp[i].typ==0){  //数值
            ++nums;
        }
        else{
            ++sigs;
        }
    }
    if(nums-sigs<1){
        return false;
    }
    if(exp[n].typ==0){      //数值
        for(i=0;i<n;++i){
            if(exp[i].id == exp[n].id){
                return false;
            }
        }
    }
    if(n==7-1){
        if(nums!=4 || sigs!=3){
            return false;
        }
        if(exp[n].typ!=1){      //不是符号
            return false;
        }
        if(cal()){
            exitflag=1;
        }
        return false;
    }
    return true;
}

bool C24p::cal()
{
    double dblstack[4];
    int    stackp=-1;
    int    i;

    for(i=0;i<7;++i){
        if(exp[i].typ==0){
            ++stackp;
            dblstack[stackp]=exp[i].num.dbl;
        }
        else{
            switch(exp[i].num.sig){
            case 1:
                dblstack[stackp-1] = dblstack[stackp-1]+dblstack[stackp];
                break;
            case 2:
                dblstack[stackp-1] = dblstack[stackp-1]-dblstack[stackp];
                break;
            case 3:
                dblstack[stackp-1] = dblstack[stackp-1]*dblstack[stackp];
                break;
            case 4:
                dblstack[stackp-1] = dblstack[stackp-1]/dblstack[stackp];
                break;
            }
            --stackp;
        }
    }
    if(fabs(dblstack[stackp]-24) <= 0.1){
        show();
        return true;
    }
    else{
        return false;
    }
}

const string C24p::getstr() const
{
    return out.str();
}

void C24p::run()
{
    putele(0);
}

void C24p::show()
{
    int expstack[4];
    int pstack=-1;

    for(int i=0;i<7;++i){
        if(exp[i].typ==0){  //数值
            ++pstack;
            expstack[pstack]=i;
        }
        else{
            exp[i].right=&exp[expstack[pstack]];
            --pstack;
            exp[i].left=&exp[expstack[pstack]];
            expstack[pstack]=i;
        }
    }
    toformulate(exp+expstack[pstack]);
}

void C24p::toformulate(C24p::Cell* root)
{
    char sigtyp;
    switch((*root).num.sig){
    case 1:
        sigtyp='+';
        break;
    case 2:
        sigtyp='-';
        break;
    case 3:
        sigtyp='*';
        break;
    case 4:
        sigtyp='/';
        break;
    }
    if(root->left->typ == 0){   //数值
        out << (*(root->left)).num.dbl;
        out << sigtyp;
    }
    else{       //符号
        if(sigprio(*root) > sigprio(*(root->left))){    //当前优先级比左边优先级高
            out << '(';
            toformulate(root->left);
            out << ')';
        }
        else{
            toformulate(root->left);
        }
        out << sigtyp;
    }
    if(root->right->typ == 0){  //数值
        out << (*(root->right)).num.dbl;
    }
    else{       //符号
        if(sigprio(*root) > sigprio(*(root->right))){
            out << '(';
            toformulate(root->right);
            out << ')';
        }
        else{
            toformulate(root->right);
        }
    }
}

char C24p::sigprio(const C24p::Cell &val)
{
    switch(val.num.sig){
    case 1:
    case 2:
        return 1;
    case 3:
    case 4:
        return 2;
    default:
        return 0;
    }
}

int main()
{
    C24p a(5,5,5,1);
    a.run();
    cout << a.getstr();
    return 1;
}


你可能感兴趣的:(计算24点)