题目
- 递归模型为从左往右,通过一个位数组记录已经访问的内容
- ....................
function main(arr) {
let sum = 0;
sum = arr.reduce((pre, now) => pre + now, 0);
if (sum % 4 !== 0) {
return false;
}
// dp 最多有 2^12 次方答案
let dp = Array(1 << arr.length).fill(0);
let len = sum / 4;
return process(arr, 0, 0, len, 4, dp);
// status 通过二进制每一位代表第 i 根火柴是否使用
// sum 表示当前拼接边的长度
// edges 表示还剩多少边没有拼接
function process(arr, status, sum, len, edges, dp) {
// 所有边都拼接完,并且每个火柴都使用
if (edges === 0) {
let n = arr.length;
// 比如4根火柴:10000 - 00001 = 1111
let s = (1 << n) - 1;
return s === status ? true : false;
}
//
if (dp[status] !== 0) {
return dp[status] == 1;
}
let ans = falase;
for (let i = 0; i <= arr.length; i++) {
// 当前火柴没用过
if (status & (1 << i === 0)) {
// 并且使用当前火柴不能超过单边长度
if (sum + arr[i] <= len) {
if (sum + arr[i] < len) {
ans = process(arr, status | (1 << i), sum + arr[i], len, edges);
} else {
ans = process(arr, status | (1 << i), 0, len, edges - 1);
}
}
}
if (ans) {
break;
}
}
// 记录当前 status 结果,主要是记录失败的结果
dp[status] = ans ? 1 : -1;
return ans;
}
}