闲来无事,做了一个这样一个程序,
能给出多个解,但不能查重
核心算法部分挺好理解,但最后的算式的表述(TranslateSol函数)上我花了很多功夫,一直没有什么很好的方法,最后基本上采用了例举各种情况的方法,不过至少还算是解决了,希望有大神能有更好的解决方案。
这里就把代码贴出来了,算法的基本思路是对四个数排列组合,每次选两个数进行加减乘除运算,记录运算方法(struct oper)
两个数算完了将结果计入数组中,代替原来的两个数,然后将这三个数在再进行递归操作,直到只有一个数且为24,将操作的记录转化为人们易读懂的表达式我没有什么好方法,就这样吧。
#include<iostream>
#include<vector>
#include<algorithm>
#include<string>
using namespace std;
struct Oper
{
int v1;
int v2;
string oper;
};
vector<float>carr;
vector<Oper>ope;
void calc(vector<float>arr, int i, int j, int operway);
int sol = 0;
void GetNum(vector<float>*arr)//传入指针或引用,否则无法实际对vector本身操作
{
int num;
int c = 0;
while (1)
{
if (c == 4)
{
break;
}
c++;
scanf_s("%d", &num);
arr->push_back(num);
}
}
void TranslateSol(vector<Oper>ope, vector<float>arr)//写得不好,可以忽视
{
vector<string>s;
s.reserve(4);
for (int i = 0; i < 4; i++)
{
s.push_back(" ");
}
string tmp;
vector<Oper>::iterator pbegin = ope.begin();
vector<Oper>::iterator pend = ope.end();
for (; pbegin != pend; pbegin++)
{
string tmp;
Oper e = *pbegin;
if (s[e.v1] == " "&&s[e.v2] == " ")
{
tmp = to_string((int)arr[e.v1]) + e.oper + to_string((int)arr[e.v2]);
}
if (s[e.v1] == " "&&s[e.v2] != " ")
{
tmp = to_string((int)arr[e.v1]) + e.oper + s[e.v2];
}
if (s[e.v1] != " "&&s[e.v2] == " ")
{
tmp = s[e.v1] + e.oper + to_string((int)arr[e.v2]);
}
if (s[e.v1] != " "&&s[e.v2] != " ")
{
tmp = s[e.v1] + e.oper + s[e.v2];
}
if (pbegin != pend - 1)
{
vector<Oper>::iterator cpbegin = pbegin + 1;
Oper q = *cpbegin;
if ((e.oper == "+" || e.oper == "-") && (q.oper == "*" || q.oper == "/"))
{
tmp = "(" + tmp + ")";
}
if ((e.oper == "+" || e.oper == "-") && (q.oper == "-")&&(q.v2==e.v1))
{
tmp = "(" + tmp + ")";
}
}
if (pbegin ==ope.begin())
{
vector<Oper>::iterator cpbegin = pbegin + 1;
Oper q = *cpbegin;
vector<Oper>::iterator zpbegin = pbegin + 2;
Oper z = *zpbegin;
if ((e.oper == "+" || e.oper == "-") && (q.oper == "+" || q.oper == "-") && (z.oper == "*" || z.oper == "/")&&(e.v1==0||e.v1==1)&&(q.v1==1||q.v2==2))
{
tmp = "(" + tmp + ")";
}
}
if (e.v1 > e.v2)
{
s[e.v2] = tmp;
s.erase(s.begin() + e.v1);
arr.erase(arr.begin() + e.v1);
}
else
{
s[e.v1] = tmp;
s.erase(s.begin() + e.v2);
arr.erase(arr.begin() + e.v2);
}
}
cout << s[0] << endl;
}
void GetSolution(vector<float>arr)
{
if (arr.size() == 1&&(*arr.begin())!=24)
{
return;
}
if (arr.size() == 1 && (*arr.begin()) == 24)
{
sol++;
for_each(ope.begin(), ope.end(), [=](Oper p){cout << p.v1 + 1 << p.oper << p.v2 + 1 << endl; });
TranslateSol(ope, carr);
cout << "第" << sol << "种方法" << endl;
return;
}
int i, j;
for (i = 0; i < arr.size(); i++)
{
for (j = i + 1; j < arr.size(); j++)
{
for (int operway = 0; operway < 6; operway++)
{
calc(arr, i, j, operway);
ope.pop_back();
}
}
}
}
void calc(vector<float>arr,int i,int j,int operway)
{
Oper* operc = new(Oper);
switch (operway)
{
case 0:
arr[i] =arr[i] + arr[j];
arr.erase(arr.begin() + j);
operc->oper = '+';
operc->v1 = (int)i;
operc->v2 = (int)j; break;
case 1:
arr[i] = arr[i] - arr[j];
arr.erase(arr.begin() + j );
operc->oper = '-';
operc->v1 = (int)i;
operc->v2 = (int)j; break;
case 2:
arr[i] = arr[i] * arr[j];
arr.erase(arr.begin() + j );
operc->oper = '*';
operc->v1 = (int)i;
operc->v2 = (int)j; break;
case 3:
arr[i] = arr[i] / arr[j];
arr.erase(arr.begin() + j );
operc->oper = '/';
operc->v1 = (int)i;
operc->v2 = (int)j; break;
case 4:
arr[i] = arr[j] - arr[i];
arr.erase(arr.begin() + j );
operc->oper = '-';
operc->v1 = (int)j;
operc->v2 = (int)i; break;
case 5:
arr[i] = arr[j] / arr[i];
arr.erase(arr.begin() + j );
operc->oper = '/';
operc->v1 =(int) j;
operc->v2 =(int) i; break;
}
ope.push_back(*operc);
GetSolution(arr);
}
int main()
{
vector<float>arr;
while (1)
{
GetNum(&arr);
carr = arr;
GetSolution(arr);
if (sol == 0)
{
cout << "无解!" << endl;
}
sol = 0;
ope.clear();
arr.clear();
}
system("pause");
}