暴力搜索算法的典型应用——24点游戏

“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;
}


猜你喜欢

转载自blog.csdn.net/qq_26286193/article/details/80444145
今日推荐