最近写d一个24点算法,不过同时可以实现输入一组数字,按所要求的答案,返回输出一条算术式子,在算法中主要利用了递归,逐层计算。
例子:((((3*3)+4)/3)*6) = 26;
下面为代码:
cpp文件:
#include"alg_Ans.h"
void main()
{
vector<double>Input;
string Exp;
int Con_record = 0;
int Ans = 24;
cout<<"How many number do you want to input..."<<endl;
cin>>Con_record;
cout<<"What is the answer do you want to get.."<<endl;
cin>>Ans;
cout<<"Input "<<Con_record<<" number..."<<endl;
for (int i = 0; i < Con_record; i++)
{
int x;
cin >> x;
Input.push_back(x);
}
Rotate(Input,Exp,Ans,Con_record);
}
头文件alg_ Ans:
#include<iostream>
#include<vector>
#include<string>
#include <cmath>
using namespace std;
const double PRECISION = 1E-6; //精度,以防在做一些除法运算时由于精度问题导致出错
/*思想:a,b,c,d => a,b,(c+*-/d)=>a,b,c=>a,c=>c==Ans?然后逐层返回计算
*/
bool Compute_Ans(vector<double>Number,string Exp,int Ans,int Con_record = 0)
{
if(Number.size() == 1)
{
if(fabs(Number[0]-Ans)<PRECISION)
{
cout<<"Success..."<<endl;
cout<<Exp<<" = "<<Ans<<endl;
return true;
}
else
{
return false;
}
}
else
{
string Exp1,Exp2;
double a,b,c;
char ch_a,ch_b;
Exp1 = Exp;
a = Number[Number.size()-1];
ch_a = a+48;
Number.pop_back();
b = Number[Number.size()-1];
ch_b = b+48;
Exp2 = ch_b;
Number.pop_back();
c = a+b;
Number.push_back(c);
if(Con_record>0)
{
Exp1 = ch_a;
}
Exp = '('+Exp1+'+'+Exp2+')';
if(Compute_Ans(Number,Exp,Ans)) return true;
Number.pop_back();
c = a*b;
Number.push_back(c);
Exp = '('+Exp1+'*'+Exp2+')';
if(Compute_Ans(Number,Exp,Ans)) return true;
Number.pop_back();
{
if(a>b)
{
c = a-b;
Number.push_back(c);
Exp = '('+Exp1+'-'+Exp2+')';
}
else
{
c = b-a;
Number.push_back(c);
Exp = '('+Exp2+'-'+Exp1+')';
}
}
if(Compute_Ans(Number,Exp,Ans)) return true;
Number.pop_back();
if(fabs(b)>PRECISION)
{
c = a/b;
Number.push_back(c);
Exp = '('+Exp1+'/'+Exp2+')';
if(Compute_Ans(Number,Exp,Ans)) return true;
}
Number.pop_back();
if(fabs(a)>PRECISION)
{
c = b/a;
Number.push_back(c);
Exp = '('+Exp2+'/'+Exp1+')';
if(Compute_Ans(Number,Exp,Ans)) return true;
}
}
return false;
}
/*Insert_Char函数用于在某一位置插入字符*/
void Insert_Char(char c1,string &str,int i)
{
if(i == 0)
{
str = c1 + str;
}
else
{
string Temp_str = str.substr(i);
str.erase(i,str.size()-i);
str = str + c1 +Temp_str;
}
}
/*Rotate 函数用来对所输入的数字进行全排列,利用的是非递归的全排列方式,主要是因为在某一情况下
计算算式中已经利用到了递归的方法,故另外利用函数编写一个非递归的,可以从中调用递归函数,而且这
样会减少占用栈空间
对输入数字进行全排列的方法是:1首先对下标进行全排列。
2然后将各个数字按所排列好的下标取数字即可得到某一数列的全排列
*/
void Rotate(vector<double>Number,string Exp,int Ans,int Con_record)
{
int count = Number.size();
vector<string>temp;
vector<string>store;
store.push_back("0");
string T_Str;
char ch_i;
for(int i = 1;i<count;i++) //递推方法 隔位插入字符,得到全排列
{
for(int j = 0;j<store.size();j++)
{
T_Str = store[j];
for(int t = 0;t<=store[j].size();t++)
{
ch_i = i+48;
Insert_Char(ch_i,T_Str,t);
temp.push_back(T_Str);
T_Str = store[j];
}
}
while(!store.empty())
{
store.pop_back();
}
store = temp;
while(!temp.empty())
{
temp.pop_back();
}
}
//以上得出下标排列
vector<double>Sort_Number;
int T_int;
bool test = false;
for(i = 0;i<store.size();i++)
{
for(int j = 0;j<Number.size();j++)
{
T_int = store[i][j];
T_int = T_int-48;
Sort_Number.push_back(Number[T_int]);
}
if(Compute_Ans(Sort_Number,Exp,Ans,Con_record))
{
test = true;
break;
}
while(!Sort_Number.empty())
{
Sort_Number.pop_back();
}
}
if(!test)
cout<<"Fail To Compute..."<<endl;
}