24点问题

本文介绍了如何运用C++编程解决24点问题,通过分治法和递归策略,将四数运算转化为子问题。代码中使用了增强for循环和std::function来实现不同运算符的组合。当只剩下一个数字且等于24时,递归结束。此算法适用于数学和计算机科学的学习者,展示了编程解决数学问题的方法。
摘要由CSDN通过智能技术生成

24点问题

24点问题:给出4个1~9的数字利用加减乘除判断是否可以得到结果为24,可以利用括号的优先级。

我们的思路是通过分治法加递归,以解决子问题的方式来应对。我们可以将4个数字运算得到24的问题转化为由 n n n个数运算得到24的子问题( 1 ≤ n ≤ 4 1\leq n\leq 4 1n4)。
我们从4个数字中任意选2个数字出来进行运算,得到的结果与剩下的两个数字形成3个数经过运算得到24的问题。接下来又是3个数字任意选2个数字得到的结果与剩下的数字形成两个数字运算得到24的问题。这里面我们就需要用到递归。
我们递归返回的条件就是当我们只剩下一个数字时,同时我们需要判断是否这一个数字就等于 24 24 24

完整代码

#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
#include<functional>
#define ll long long
#define INF 0x7fffffff
using namespace std;
struct Number{
	double num;
	string numstr;
	Number(double num_, string numstr_){
		num = num_;
		numstr = numstr_;
	}
	Number(){};
};
vector<Number> numbers;
std::function<bool(const Number&, const Number&, Number&)> acopts[]={
	[](const Number& num1, const Number& num2, Number& res){
		res.num = num1.num+num2.num;
		res.numstr = '(' + num1.numstr + '+' + num2.numstr + ')';
		return true;
	},
	[](const Number& num1, const Number& num2, Number& res){
		res.num = num1.num-num2.num;
		res.numstr = '(' + num1.numstr + '-' + num2.numstr + ')';
		return true;
	},
	[](const Number& num1, const Number& num2, Number& res){
		res.num = num1.num*num2.num;
		res.numstr = '(' + num1.numstr + '*' + num2.numstr + ')';
		return true;
	},
	[](const Number& num1, const Number& num2, Number& res){
		if(num2.num==0)return false;
		res.num = num1.num/num2.num;
		res.numstr = '(' + num1.numstr + '/' + num2.numstr + ')';
		return true;
	}
};
void Calculation(vector<Number>& nums){
	size_t res = nums.size();
	if(res==1){
		if(nums[0].num == 24){
			cout<<nums[0].numstr<<" = "<<nums[0].num<<endl;
		}
		return ;
	}
	for(int i = 0;i < res;i++){
		for(int j = 0;j < res;j++){
			if(i==j)continue;
			for(auto&opt : acopts){
				Number new_num;
				if(opt(nums[i], nums[j], new_num)){
					vector<Number> sub_num;
					sub_num.push_back(new_num);
					for(int k = 0;k < res;k++){
						if(k!=i&&k!=j){
							sub_num.push_back(nums[k]);
						}
					}
					Calculation(sub_num);
				}
			}
		}
	}
}
void solve(){
	for(int i = 0;i < 4;i++){
		int n;string s;
		cin>>n;
		s = to_string(n);//将int型转化为字符串string型
		Number m = {(double)n,s};
		// 这里加个(double)是因为我们计算的时候是会产生浮点型的,之所以不是输入的时候就是double型是为了防止转string型时出现小数部分
		numbers.push_back(m);
	}
	Calculation(numbers);
}
int main(){
	solve();
	return 0;
}

结果如图所示:
在这里插入图片描述

代码部分片段分析

  1. auto&opt : acopts:这里我们用到了增强for循环,类似于for(auto 元素 :数据集合)形式。
  2. auto可以在声明变量的时候根据变量初始值的类型自动为此变量选择匹配的类型。
  3. function:头文件为#include<functional>std::function是一个通用的多态函数包装器,可以调用普通函数、Lambda函数、仿函数、bind对象、类的成员函数和指向数据成员的指针。它是一个模板。在创建function实例时,必须指明类型。

比如:

function<int(int,int)>

意思是我们声明了一个function类型,它可以接受两个int类型参数并返回一个int类型的可调用函数。
我们还可以这样

int func(int a, int b){
	return a*b;
}
int main(){
	std::function<int(int,int)> Func = func;
	Func(2,3);
	return 0;
}

问题来自女朋友的分享~ ( ̄▽ ̄~) (~ ̄▽ ̄)~

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值