“24点”是个棋牌类益智游戏,要求四个数字运算结果等于二十四。这种类型的题目可以通过编写程序让计算机完成。一个更具有普遍性的题目如下:
每次给若干个数和一个目标数,让你判断,利用这些数能否通过简单的运算(加,减,乘,除)得到那个目标数。如果能则输出目标数,否则输出这几个数能凑到的小于目标数的最大的那个数。备注:要求每个数都要用到,并且除法必须要求能够进行整除,否则就不能进行除法;例如,4/2可以,1/7和9/4就不可以。
例1:
输入五个数为:1 2 3 7 100;目标数为:573
输出:573 (因为:(((100-1)*2)-7)*3 = 573)
例2:
输入五个数为:67 69 58 22 2;目标数为:929
输出:923 (因为:(22-(67-58))*(69+2)=923)
例3:
输入四个数为:1 3 7 13;目标数为:30
输出:30(因为:((7*13)-1)/3=30)
用暴力搜索算法枚举所有可能性即可解决此问题。在这里我介绍一下我的解决思路:首先用一个动态数组(在C++中,推荐用STL标准库中的vector来实现动态数组)储存这几个数。然后每一步在数组中任选两个数,对它们进行其中一种运算:+、-、*、/(注意,减法和除法不满足交换律),并在原数组中删除选出的那两个数,把运算结果添加到数组中。经过这一步后,数组的长度就会-1。依此类推,直到数组的长度变为1,搜索结束,数组中剩下的那个元素就是结果,将它与之前得到的结果进行比较,选取更优的结果。
这里作一点小改进:
用一个vector来保存每一步对数字的操作,这样就可以看到具体的过程和步骤。下面的代码中,我用一个vector
#include
#include
using namespace std;
void search(vector left, int &result, vector& operators, vector tmp_operators, int target)
{
if (left.size() == 1) {
//left中只剩一个元素,搜索结束,比较结果,选取更优的那个
if (left[0] <= target && left[0] > result) {
result = left[0];
operators = tmp_operators;
}
}
else {
//在left中选两个数字,对它们进行+、-、*、/操作
//+ - * /分别用0 1 2 3表示
vector tmp_left, tmp_tmpoperators;
for (int i = 0; i < left.size(); i++) {
for (int j = i + 1; j < left.size(); j++) {
tmp_left = left;
int tmp1 = tmp_left[i], tmp2 = tmp_left[j];
tmp_left.erase(tmp_left.begin() + j);
// +,tmp1和tmp2即使次序换了,结果不变
tmp_tmpoperators = tmp_operators;
tmp_left[i] = tmp1 + tmp2;
tmp_tmpoperators.push_back(tmp1);
tmp_tmpoperators.push_back(tmp2);
tmp_tmpoperators.push_back(tmp1+tmp2);
tmp_tmpoperators.push_back(0);
search(tmp_left, result, operators, tmp_tmpoperators, target);
// -,这里要注意,tmp1-tmp2和tmp2-tmp1是不同的结果
tmp_tmpoperators = tmp_operators;
tmp_tmpoperators.push_back(tmp1);
tmp_tmpoperators.push_back(tmp2);
tmp_tmpoperators.push_back(tmp1 - tmp2);
tmp_tmpoperators.push_back(1);
tmp_left[i] = tmp1 - tmp2;
search(tmp_left, result, operators, tmp_tmpoperators, target);
tmp_tmpoperators = tmp_operators;
tmp_tmpoperators.push_back(tmp2);
tmp_tmpoperators.push_back(tmp1);
tmp_tmpoperators.push_back(tmp2 - tmp1);
tmp_tmpoperators.push_back(1);
tmp_left[i] = tmp2 - tmp1;
search(tmp_left, result, operators, tmp_tmpoperators, target);
// *,tmp1和tmp2即使次序换了,结果不变
tmp_tmpoperators = tmp_operators;
tmp_tmpoperators.push_back(tmp1);
tmp_tmpoperators.push_back(tmp2);
tmp_tmpoperators.push_back(tmp1 * tmp2);
tmp_tmpoperators.push_back(2);
tmp_left[i] = tmp1 * tmp2;
search(tmp_left, result, operators, tmp_tmpoperators, target);
// /,这里要注意,tmp1/tmp2和tmp2/tmp1是不同的结果
if (tmp2 != 0 && tmp1%tmp2 == 0) {
tmp_tmpoperators = tmp_operators;
tmp_tmpoperators.push_back(tmp1);
tmp_tmpoperators.push_back(tmp2);
tmp_tmpoperators.push_back(tmp1 / tmp2);
tmp_tmpoperators.push_back(3);
tmp_left[i] = tmp1 / tmp2;
search(tmp_left, result, operators, tmp_tmpoperators, target);
}
if (tmp1 != 0 && tmp2%tmp1 == 0) {
tmp_tmpoperators = tmp_operators;
tmp_tmpoperators.push_back(tmp2);
tmp_tmpoperators.push_back(tmp1);
tmp_tmpoperators.push_back(tmp2 / tmp1);
tmp_tmpoperators.push_back(3);
tmp_left[i] = tmp2 / tmp1;
search(tmp_left, result, operators, tmp_tmpoperators, target);
}
}
}
}
}
int main()
{
int m;
cout << "输入数字的个数:" << endl;
cin >> m;
vector num(m);
int target;
int res = INT_MIN;
cout << "输入" << m << "个数字:" << endl;
for (int i = 0; i < m; i++) {
cin >> num[i];
}
cout << "输入目标数:" << endl;
cin >> target;
vector finaloperators, tmpoperators;
search(num, res, finaloperators, tmpoperators, target);
cout << "显示过程:" << endl;
for (int i = 0; i < m - 1; i++) {
cout << finaloperators[i * 4] << ' ';
if (finaloperators[i * 4 + 3] == 0) cout << '+' << ' ';
else if (finaloperators[i * 4 + 3] == 1) cout << '-' << ' ';
else if (finaloperators[i * 4 + 3] == 2) cout << '*' << ' ';
else if (finaloperators[i * 4 + 3] == 3) cout << '/' << ' ';
cout << finaloperators[i * 4 + 1] << " = " << finaloperators[i * 4 + 2] << endl;
}
system("pause");
return 0;
}