“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<int>来保存每一步的操作。vector<int>大小为4*(m-1),m为输入的数字的个数。vector以四个数字为一个分组代表一步操作,第一个和第二个数字表示操作数,第三个数字表示结果,第四个数字表示操作符:0为+、1为-、2为*、3为/。
#include <iostream> #include <vector> using namespace std; void search(vector<int> left, int &result, vector<int>& operators, vector<int> 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<int> 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<int> 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<int> 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; }