来源:力扣(LeetCode)
题目分析
括号运算符仅仅表达了一个运算顺序,可以不用考虑,实际的运算类型就 4 种。一共只有 4 个数,因此所有组合的可能性是有限的。
DFS 算法就是对当前的所有可能的操作进行枚举:当前的操作即从可选的数字中挑 2 个进行每种运算的尝试。
代码示例
constexpr double ex = 1e-6;//精度
constexpr double tag = 24;//目标值
class Solution {
public:
bool judgePoint24(vector<int>& nums) {
vector<double> curnums;
for( int i = 0;i < nums.size();i++)
{
curnums.emplace_back(double(nums[i]));
}
return dfs(curnums);
}
bool dfs(vector<double> &nums)
{
//边界条件:没有选择了,直接返回
if( nums.size() == 0)
return false;
//基线条件:只有一种选择,直接判断结果
if( nums.size() == 1)
return abs(tag - nums[0] ) < ex;
//当前能做的选择:挑 2 个数,进行 4 种运算
for( int i = 0;i < nums.size();++i)//挑选第一个数
{
for( int j = 0;j < nums.size();++j)// 挑选第二个数
{
if( i != j )
{
vector<double> curnums;//保存剩余元素
for( int k = 0;k < nums.size();++k)
{
if( k != i && k != j)
curnums.emplace_back(nums[k]);
}
//尝试每一种运算
// a+b
curnums.emplace_back( nums[i]+nums[j] );
bool isok = dfs( curnums);
curnums.pop_back();
if( isok) return true;
// a- b
curnums.emplace_back( nums[i]-nums[j] );
isok = dfs( curnums);
curnums.pop_back();
if( isok ) return true;
// b-a 已遍历了所有 a 和 b 的组合,没必要再进行 b-a
/*
curnums.emplace_back( nums[j]-nums[i] );
isok = dfs( curnums);
curnums.pop_back();
if( isok ) return true;*/
// a*b
curnums.emplace_back( nums[i]*nums[j] );
isok = dfs( curnums);
curnums.pop_back();
if( isok) return true;
// a / b
if( nums[j] != 0 )
{
curnums.emplace_back( nums[i] / nums[j] );
isok = dfs( curnums);
curnums.pop_back();
if( isok) return true;
}
// b /a
/*
if( nums[i]!= 0 )
{
curnums.emplace_back( nums[j] / nums[i] );
isok = dfs( curnums);
curnums.pop_back();
if( isok) return true;
} */
}
}
}
return false;
}
};