1.16 24点游戏

问题:

给玩家4张牌,每张牌的面值在1-13之间,允许其中有数值相同的牌,采用加、减、乘、除四则运算,允许中间运算存在小数,并且可以使用括号,但每张牌只能用一次。构造表达式,使其结果为24.

解法一:

利用递归,强搜!

代码如下:

#include <iostream>
#include <string>
#include <cmath>

using namespace std;

const double Threshold = 1E-6;
const int CardsNumber = 4;
const int ResultValue = 24;
double number[CardsNumber];
string result[CardsNumber];

bool pointsGame(int n) {
	if(1 == n) {
		if(fabs(number[0] - ResultValue) < Threshold) {
			cout << result[0] << endl;
			return true;
		}else return false;
	}
	for(int i = 0; i < n; ++i) {
		for(int j = i + 1; j < n; ++j) {
			double a, b;
			string expa, expb;
			a = number[i];
			b = number[j];
			number[j] = number[n - 1];
				
			expa = result[i];
			expb = result[j];
			result[j] = result[n - 1];
				
			number[i] = a + b;
			result[i] = '(' + expa + '+' + expb + ')';
			if(pointsGame(n - 1)) return true;

			number[i] = a - b;
			result[i] = '(' + expa + '-' + expb + ')';
			if(pointsGame(n - 1)) return true;

			number[i] = b - a;
			result[i] = '(' + expb + '-' + expa + ')';
			if(pointsGame(n - 1)) return true;

			number[i] = a * b;
			result[i] = '(' + expa + '*' + expb + ')';
			if(pointsGame(n - 1)) return true;

			if(b != 0) {
				number[i] = a / b;
				result[i] = '(' + expa + '/' + expb + ')';
				if(pointsGame(n - 1)) return true;
			}

			if(a != 0) {
				number[i] = b / a;
				result[i] = '(' + expb + '/' + expa + ')';
				if(pointsGame(n - 1)) return true;
			}
			number[i] = a;
			number[j] = b;
			result[i] = expa;
			result[j] = expb;
		}			
	}
	return false;
}

int main() {
	int x;
	for(int i = 0; i < CardsNumber; ++i) {
		cin >> x;
		number[i] = x;
		char buffer[20];
		itoa(x, buffer, 10);
		result[i] = buffer;
	}
	if(pointsGame(CardsNumber)) cout << "successed" << endl;
	else cout << "Failed" << endl;
	return 0;
}

解法二:

利用书中讲的递归的方法,f(A)为对集合A中的元素进行所有可能的四则混合运算所得到的值。

Fork(A, B)代表对A, B中的元素进行四则运算的结果。

在下面的代码中,用二进制来代表一个集合,全集为1111,意思就是这个集合里面有4个数字。以此类推

伪代码:

24Game(Array) {  //Array为初始输入的集合,其中的元素表示为
	for(int i = 1; i <= 2deNcifang - 1; ++i) S[i] = kongji;		//初始化将S中的各个集合置为空集
	for(int i = 0; i < n; ++i) S[2deIcifang] = {ai};            //先对每个只有一个元素的真子集赋值,既为该元素本身
	for(int i = 1; i <= 2deNcifang - 1; ++i) S[i] = f(i);
	Check(S[2deNcifang-1]);
}

f(int i) {
	if(S[i] != kongji) return S[i];
	for(int x = 1; x < i; ++x)      //只有小于i的x才可能称为i的真子集
		if(x & i == x)     //&为与运算,只有当括号内的表达式成立的时候,x才为i的子集, 
			S[i] U= Fork(f(x), f(i-x));    //这里的U为并运算,在Fork的过程中,要去除中间结果
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值