• 一个类24点问题算法实现


    问题描述:
       在game.in中给定任意5个整数和期望数EXPECTION_VAL,使用+ - * /进行对这5个数进行运算,每个运算操作只能使用一次,()可以使用无数次。
       输出一个计算结果或者证明无合适解。

    算法思路:
      一个基本的解析算式是exp = (exp | num ) op (exp | num)
      接下来使用动态规划进行计算就行了,将最近操作的两个数加入到算子集合重新计算,如此递归,直至找到解或者计算完所有的可能。
      对于calculate函数相关的因素包括(算子集合,操作子集合)。
      递归边界应该是算子集合数目为2并且操作子数目为1。

    说明:
      本程序的实现没有怎么优化,有很多冗余可以使用记录exp算式的方法进行剔除,  
    /*******************************************************************************
     * created:2012/04/26
     * created:2012-4-26   11:04
     * file base:main
     * file ext:cpp
     * author:xiaoyang hityixiaoyang@gmail.com
    ********************************************************************************
     * 描述:
     * 在game.in中给定任意5个整数和期望数EXPECTION_VAL,使用+ - * /进行对这5
     * 个数进行运算,每个运算操作只能使用一次,()可以使用无数次。
     * 输出一个计算结果或者证明无合适解。
    ********************************************************************************/
    #include <iostream>
    #include <vector>
    #include <fstream>
    #include <algorithm>
    #include <string>
    #include <stack>
    
    using namespace std;
    
    long CalCount = 0;
    
    const char* INPUT_FILE  = "game.in";
    const char* OUTPUT_FILE = "game.out";
    const char* RES_FILE = "game.res";
    const int NUMBER_COUNT  = 5;
    //const 
    int EXPECTION_VAL = 0;
    
    vector<int> Nums;
    //vector<int> OrgNums;
    vector<char> Ops;
    //vector<char> OrgOps;
    ofstream fout;
    ofstream fres;
    typedef struct exp {
        int num1;
        int num2;
        char op;
    } Exp;
    stack<exp> ResStr;
    
    void PrintRes()
    {
        fout<< "--------------------" <<endl;
        fres<< "--------------------" <<endl;
        while (!ResStr.empty()) {
            fout << ResStr.top().num1  << ","  << ResStr.top().num2 << "," << ResStr.top().op << endl;
            fres << ResStr.top().num1  << ","  << ResStr.top().num2 << "," << ResStr.top().op << endl;
            ResStr.pop();
        }
        fout<< "--------------------\nend!" <<endl;
        fres <<endl;
    }
    
    void AddRes(int num1,int num2, char op)
    {
        Exp tmpExp;
        tmpExp.num1 = num1;
        tmpExp.num2 = num2;
        tmpExp.op = op;
        ResStr.push(tmpExp);
    }
    
    void Config()
    {
        int tmp = 0;
        ifstream fin(INPUT_FILE);
        if (fin.eof()) {
            exit(-2);
        }
    
        for (int i = 0; i < NUMBER_COUNT; i++) {
            fin >> tmp;
            Nums.push_back(tmp);
        }
    
        fin >> EXPECTION_VAL;
        Ops.push_back('+');
        Ops.push_back('-');
        Ops.push_back('*');
        Ops.push_back('/');
    
        fout.open(OUTPUT_FILE);
        fout << "steps:"<<endl;
    
        fres.open(RES_FILE);
        fres << "steps:"<<endl;
    }
    
    
    /*
     * ret:
     *        -1,calculate failed
     *        0,success
     */
    int Calculate(vector<int>& iNums,vector<char>& iOps)
    {
        //unsigned int i=0, j=0, k=0;
        int newNum1 = 0, newNum2 = 0;
        vector<char>::iterator vc_it;
    
        /**/
        if ((iOps.size() == 1) || (iNums.size() == 2)) {
            int res = -1;
            if (iOps[0] == '+') {
                res = iNums[0] + iNums[1];
                /*(n,n,op) res:*/
                fout << "(" << iNums[0] << "," << iNums[1] << "," << iOps[0] << ") res:" << res << endl;
                if(res == EXPECTION_VAL) {
                    goto suc;
                } else {
                    goto fail;
                }
            } else if (iOps[0] == '-') {
                res = iNums[0] - iNums[1];
                /*(n,n,op) res:*/
                fout << "(" << iNums[0] << "," << iNums[1] << "," << iOps[0] << ") res:" << res << endl;
                if(res == EXPECTION_VAL) {
                    goto suc;
                } else {
                    fout << "failed:recalculate!" << endl;
                }
    
                res = iNums[1] - iNums[0];
                /*(n,n,op) res:*/
                fout << "(" << iNums[1] << "," << iNums[0] << "," << iOps[0] << ") res:" << res << endl;
                if(res == EXPECTION_VAL) {
                    goto suc;
                } else {
                    goto fail;
                }
            } else if (iOps[0] == '*') {
                res = iNums[0] * iNums[1];
                /*(n,n,op) res:*/
                fout << "(" << iNums[0] << "," << iNums[1] << "," << iOps[0] << ") res:" << res << endl;
                if(res == EXPECTION_VAL) {
                    goto suc;
                } else {
                    goto fail;
                }
            } else if (iOps[0] == '/') {
                if((iNums[0] == 0) | (iNums[1] == 0)) {
                    res = 0;
                    fout << "(" << iNums[0] << "," << iNums[1] << "," << iOps[0] << ") res:" << res << endl;
                    if(res == EXPECTION_VAL) {
                        goto suc;
                    } else {
                        goto fail;
                    }
                } else {
                    res = (int)(iNums[0] / iNums[1]);
                    fout << "(" << iNums[0] << "," << iNums[1] << "," << iOps[0] << ") res:" << res << endl;
                    if(res == EXPECTION_VAL) {
                        goto suc;
                    } else {
                        fout << "failed:recalculate!" << endl;
                    }
    
                    res = (int)(iNums[1] / iNums[0]);
                    fout << "(" << iNums[1] << "," << iNums[0] << "," << iOps[0] << ") res:" << res << endl;
                    if(res == EXPECTION_VAL) {
                        goto suc;
                    } else {
                        goto fail;
                    }
                }
            } else {
                cout << "error: unknown exception @"<< __LINE__ << endl;
                return -1;
            }
    
    suc:
            CalCount++;
            return 0;
    fail:
            fout << "failed:recalculate!" << endl;
            CalCount++;
            return -1;
        }
    
    
        /*it's important!used for resume stack*/
        vector<int> OrgNums(iNums);
        vector<char> OrgOps(iOps);
        /*choose 2 numbers,calculate them*/
        for (unsigned int i = 0; i < OrgNums.size(); i++) {
            newNum1 = iNums.at(i);
            iNums.erase(iNums.begin()+i);
            
            /*it's important!used for resume stack*/
            vector<int> OrgNums2(iNums);
            for(unsigned int j = 0; j < iNums.size(); j++) {
                newNum2 = iNums.at(j);
                iNums.erase(iNums.begin()+j);
    
                fout << "\t" << newNum1 << "," << newNum2 <<endl;
                /*+*/
                vc_it = find(iOps.begin(),iOps.end(),'+');
                if(vc_it != iOps.end()) {
                    fout << "(" << newNum1 << "," << newNum2 << ",+)" << endl;
                    iNums.push_back(newNum1+newNum2);
                    iOps.erase(vc_it);
                    if (Calculate(iNums,iOps) == 0) {
                        AddRes(newNum1,newNum2,'+');
                        cout << "success:got it!" << endl;
                        fout << "success:got it!" << endl;
                        return 0;
                    } else {
                        iNums.pop_back();
                        iOps.clear();
                        iOps = OrgOps;
                    }
                }
    
    
                /*-*/
                vc_it = find(iOps.begin(),iOps.end(),'-');
                if(vc_it != iOps.end()) {
                    fout << "(" << newNum1 << "," << newNum2 << ",-)" << endl;
                    iNums.push_back(newNum1-newNum2);
                    iOps.erase(vc_it);
                    if (Calculate(iNums,iOps) == 0) {
                        AddRes(newNum1,newNum2,'-');
                        cout << "success:got it!" << endl;
                        fout << "success:got it!" << endl;
                        return 0;
                    } else {
                        iNums.pop_back();
                        iOps.clear();
                        iOps = OrgOps;
                    }
    
                    fout << "(" << newNum2 << "," << newNum1 << ",-)" << endl;
                    vc_it = find(iOps.begin(),iOps.end(),'-');
                    if(vc_it != iOps.end()) {
                        iNums.push_back(newNum2-newNum1);
                        iOps.erase(vc_it);
                        if (Calculate(iNums,iOps) == 0) {
                            AddRes(newNum2,newNum1,'-');
                            cout << "success:got it!" << endl;
                            fout << "success:got it!" << endl;
                            return 0;
                        } else {
                            iNums.pop_back();
                            iOps.clear();
                            iOps = OrgOps;
                        }
                    }
                }
    
                /***/
                vc_it = find(iOps.begin(),iOps.end(),'*');
                if(vc_it != iOps.end()) {
                    fout << "(" << newNum1 << "," << newNum2 << ",*)" << endl;
                    iNums.push_back(newNum1*newNum2);
                    iOps.erase(vc_it);
                    if (Calculate(iNums,iOps) == 0) {
                        AddRes(newNum1,newNum2,'*');
                        cout << "success:got it!" << endl;
                        fout << "success:got it!" << endl;
                        return 0;
                    } else {
                        iNums.pop_back();
                        iOps.clear();
                        iOps = OrgOps;
                    }
                }
    
    
                /*/*/
                vc_it = find(iOps.begin(),iOps.end(),'/');
                if(vc_it != iOps.end()) {
                    if (newNum2 != 0) {
                        fout << "(" << newNum1 << "," << newNum2 << ",/)" << endl;
                        if (newNum1%newNum2 == 0) {
                            iNums.push_back((int)(newNum1/newNum2));
                            iOps.erase(vc_it);
                            if (Calculate(iNums,iOps) == 0) {
                                AddRes(newNum1,newNum2,'/');
                                cout << "success:got it!" << endl;
                                fout << "success:got it!" << endl;
                                return 0;
                            } else {
                                iNums.pop_back();
                                iOps.clear();
                                iOps = OrgOps;
                            }
                        }
                    }
    
                    vc_it = find(iOps.begin(),iOps.end(),'/');
                    if(vc_it != iOps.end()) {
                        if (newNum1 != 0) {
                            if (newNum2%newNum1 == 0) {
                                fout << "(" << newNum2 << "," << newNum1 << ",/)" << endl;
                                iNums.push_back((int)(newNum2/newNum1));
                                iOps.erase(vc_it);
                                if (Calculate(iNums,iOps) == 0) {
                                    AddRes(newNum2,newNum1,'/');
                                    cout << "success:got it!" << endl;
                                    fout << "success:got it!" << endl;
                                    return 0;
                                } else {
                                    iNums.pop_back();
                                    iOps.clear();
                                    iOps = OrgOps;
                                }
                            }
                        }
                    }
                }
    
    
                iNums.clear();
                iNums = OrgNums2;
            }
    
           
    
            iNums.clear();
            iNums = OrgNums;
        }
    
       
        //iOps = OrgOps;
        /*no res*/
        cout << "no answer!" << endl;
        fout << "no answer!" << endl;
    
        return -1;
    }
    
    int main(void)
    {
        Config();
        Calculate(Nums,Ops);
        PrintRes();
        cout << "Calculate times:" << CalCount << endl;
        fout << "Calculate times:" << CalCount << endl;
        fres << "Calculate times:" << CalCount << endl;
        fout.flush();
        fres.flush();
        getchar();
        return 0;
    }

    使用这个代码前需要先家建立1个输入文件game.in,并在文件里输入5个算子和一个期望值。

    输出结果会在game.res、 game.out文件中显示

  • 相关阅读:
    MYSQL 神奇的操作insert into test select * from test;
    mysql innodb与myisam存储文件的区别
    centos 普通用户 和 root 相互切换方法
    MySQL
    mysql查看数据库表数量
    PHP是单线程还是多线程?
    PHP如何解决网站大流量与高并发的问题(一)
    PHP如何解决网站大流量与高并发的问题(二)
    Work at home, Work as a distributed team | TVP思享
    区块链上的虚拟开放世界游戏是怎样的?| TVP思享
  • 原文地址:https://www.cnblogs.com/yixiaoyang/p/2471096.html
Copyright © 2020-2023  润新知