问题描述:
在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文件中显示