题解 | #24点游戏算法#

24点游戏算法

https://www.nowcoder.com/practice/fbc417f314f745b1978fc751a54ac8cb

1. 先两两组合,一共四个数,分成互不相同的两个一组(顺序无所谓),共有6种分法。比如数组 [4, 1, 3, 7] 可以分成[4,1]、[4,3]、[4,7]、[1,3]、[1,7]、[3,7]
2. 将以上6种分法进行遍历,传入计算函数calc24, 一共传入两个参数:selected 被选中的数组,与之配对的剩余数组left。 比如原数组[4, 1, 3, 7] ,我们选[4,1],则剩下[3, 7] , 将这两个数组都传入计算函数。
3. 在计算函数calc24 内部,先判断 left的长度,如果left 长度为2,则意味着这是该组初次进入计算,此时需计算 selected[] 的结果 和 left[] 的结果能不能得出24。比如:原数组[1,9,6,3],分组后 取一组 selected 为[1,9],则剩余left为[6,3] ,此时需计算[1,9]的结果[6,3]的结果能不能组成24,此例是可以组成的,比如 9-1 = 8; 6-3 = 3; 8*3 = 24。
- 如果能,则标记flag,退出递归,return
- 如果不能得出24,则将left 数组里每一个数,单独与 selected[] 数组的6种加减乘除运算结果遍历(注意:减法和除法各有两种结果),分别组成新的 selected[] 和 left[]。比如:原数组[2,4,5,8],selected为 [2,4] , left 为[5, 8]。selected里面两个数加减乘除res1[] 、 left里两个数加减乘除res2[], res1和 res2 无法组成24, 则将res1[]里每个元素分别于 5 和8 组成新的selected,比如 res1 其中一个元素为2+4 = 6, 6与left 中的5 组合,组成[6, 5], left 中剩余[8], 则新的selected数组为[6, 5] , 新的 left 数组为[8]。
4. 递归退出条件,① 找到24,flag标记位true,return; ② left 数组为空,flag还是false,则没有找到符合的组合计算方式,return false

const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;

void (async function () {
    // Write your code here
    while ((line = await readline())) {
        let cards = line.split(" ").map(Number);
        let flag = false; // 标志位,标记有没有找到能算出24的解法,默认为false,还没找到
        for (let i = 0; i < cards.length - 1; i++) {
            for (let j = i + 1; j < cards.length; j++) {
                let t = [cards[i], cards[j]];
                let cl = [...cards]; // 一定要深拷贝
                cl.splice(i, 1);
                cl.splice(j - 1, 1);
                calc24(t, cl);
            }
        }
        console.log(flag);

        function calc24(selected, left) {
            // selected 数组,被选中的组合的元素,left 被选中后剩下的元素
            let save_calc = six_op(selected[0], selected[1]);
            if (left.length == 0) {
                // 如果left数组为空,则说明已经递归完成,只需判断selected数组里的两个元素能不能组成24即可。
                for (let i = 0; i < save_calc.length; i++) {
                    if (Math.abs(save_calc[i] - 24) <= 0.0001) {
                        flag = true;
                        return true;
                    }
                }
            } else if (left.length == 2) {
                // 如果left数组长度为2,则说明这是刚进入第一次递归,calc24()传入的两个参数是[1,9] [6,3] 这种,则需计算[1,9]的结果 和 [6,3]的结果能不能组成24,此例是可以组成的,比如 9-1 = 8; 6-3 = 3; 8*3 = 24
                let save_left_calc = six_op(left[0], left[1]);
                save_calc.forEach((item, i) => {
                    // 6*6
                    save_left_calc.forEach((nt, j) => {
                        if (
                            Math.abs(item + nt - 24) <= 0.000001 ||
                            Math.abs(item - nt - 24) <= 0.000001 ||
                            Math.abs(nt - item - 24) <= 0.000001 ||
                            Math.abs(item * nt - 24) <= 0.000001 ||
                            Math.abs(item / nt - 24) <= 0.000001 ||
                            Math.abs(nt / item - 24) <= 0.000001
                        ) {
                            flag = true;
                            return true;
                        }
                    });
                });
            }

            if (!flag) {
                if (left.length == 0) {
                    // left数组都用完了,还是没找到,则说明没有满足24的解法
                    return false;
                } else {
                    // left 数组还有,继续跑
                    for (let j = 0; j < left.length; j++) {
                        let r = [...left];
                        r.splice(j, 1);
                        save_calc.forEach((item) => {
                            calc24([item, left[j]], r); //  加
                        });
                    }
                }
            }
        }

        function six_op(num1, num2) {
            let res = [];
            res.push(num1 + num2); // 加
            res.push(num1 - num2); // 减1
            res.push(num2 - num1); // 减2
            res.push(num1 * num2); // 乘
            res.push(parseFloat((num1 / num2).toFixed(7))); // 除1
            res.push(parseFloat((num2 / num1).toFixed(7))); // 除2
            return res;
        }
    }
})();

全部评论

相关推荐

点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务