一个类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 [email protected]

********************************************************************************

 * 描述:

 * 在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文件中显示

你可能感兴趣的:(算法)