679. 24 Game
You have 4 cards each containing a number from 1 to 9. You need to judge whether they could operated through *
, /
, +
, -
, (
, )
to get the value of 24.
Example 1:
Input: [4, 1, 8, 7]
Output: True
Explanation: (8-4) * (7-1) = 24
Example 2:
Input: [1, 2, 1, 2]
Output: False
Note:
1. The division operator /
represents real division, not integer division. For example, 4 / (1 - 2/3) = 12.
2. Every operation done is between two numbers. In particular, we cannot use - as a unary operator. For example, with [1, 1, 1, 1]
as input, the expression -1 - 1 - 1 - 1
is not allowed.
3. You cannot concatenate numbers together. For example, if the input is [1, 2, 1, 2]
, we cannot write this as 12 + 12
.
题目大意
给定一个由四个整数组成的序列,判断其能否通过加、减、乘、除,最终得到24
。
注意:
1. 可以进行小数运算
2. 不可以将-
当作一元操作符。
3. 不可以将数字进行合并。
解题思路
使用DFS的思路,穷举所有的可能,一旦发现满足的答案,则返回正确;当穷举完所有可能,仍不存在解,则说明这组序列不存在计算可以获得24
.
每次将两个数字的计算结果保存在其中一个数字的位置上,同时,将另一个数字的位置设为已被访问,不允许再次访问。再将这个计算结果和当前使用过的数字总数递归调用函数自身。每组数对,分别执行加减乘除四个操作,当得到24
时,立即结束返回结果;如果没有得到24
时,将刚刚被赋值的位置还原会原来的值,并且取出另一个位置被访问的标识(这一步极为重要,保证在回溯时,还原之前的操作)。
使用cur
变量确定当前已经访问到底几个数字,当访问到第4个数字时,在数组中寻找是否存在没被访问,且等于24
的节点,如果存在,则说明这四个数字可以计算得到24
。
细节:
1. 因为使用的是浮点数,所以难免存在精度误差,为了避免精度误差,所以将 abs(x) < 1e-4
等同于x == 0
.
2. 零不可以作为除数。
3. 使用vis
记录当前节点是否已经被访问过。
代码实现
class Solution {
public:
const double EPS = 1e-4;
bool dfs(vector<double>& nums, deque<bool>& vis, int cur) {
if (cur == 4) {
for (int i = 0; i < 4; i++) {
if (!vis[i] && abs(nums[i]-24.0) < EPS) { return true; }
}
return false;
}
for (int i = 0; i < 4; i++) {
if (vis[i]) continue;
for (int j = i+1; j < 4; j++) {
if (vis[j]) continue;
vis[j] = true;
double x = nums[i];
double y = nums[j];
// +
nums[i] = x+y;
if (dfs(nums, vis, cur+1)) { return true; }
// *
nums[i] = x*y;
if (dfs(nums, vis, cur+1)) { return true; }
// -
nums[i] = x-y;
if (dfs(nums, vis, cur+1)) { return true; }
nums[i] = y-x;
if (dfs(nums, vis, cur+1)) { return true; }
// /
if (abs(y) > EPS) {
nums[i] = x / y;
if (dfs(nums, vis, cur+1)) { return true; }
}
if (abs(x) > EPS) {
nums[i] = y / x;
if (dfs(nums, vis, cur+1)) { return true; }
}
/** important step **/
nums[i] = x;
vis[j] = false;
}
}
return false;
}
bool judgePoint24(vector<int>& nums) {
vector<double> doubleNums(4, 0.0);deque<bool> vis(4, false);
int size = nums.size();
for (int i = 0; i < size; i++) {
doubleNums[i] = nums[i];
}
return dfs(doubleNums, vis, 1);
}
};