24点问题
24点问题:给出4个1~9的数字利用加减乘除判断是否可以得到结果为24,可以利用括号的优先级。
我们的思路是通过分治法加递归,以解决子问题的方式来应对。我们可以将4个数字运算得到24的问题转化为由
n
n
n个数运算得到24的子问题(
1
≤
n
≤
4
1\leq n\leq 4
1≤n≤4)。
我们从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;
}
结果如图所示:
代码部分片段分析
auto&opt : acopts
:这里我们用到了增强for循环,类似于for(auto 元素 :数据集合)
形式。auto
可以在声明变量的时候根据变量初始值的类型自动为此变量选择匹配的类型。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;
}
问题来自女朋友的分享~ ( ̄▽ ̄~) (~ ̄▽ ̄)~