动态规划算法限定条件最优解

上一篇文章我们讲到动态规划算法一般情况下的简单实现,但是游戏中对于道具的数量是会做限定的,在道具数量不足的情况下,如何构建我们子问题的最优解呢?我们接着分析


1.png

观察上图,此时我们引入了MAX代表结果为无最优解,我们构造了如上篇文章般的最优解表格。得出结论如果在拥有两个2小时效果的时间道具及一个3小时效果的时间道具时,目标为6小时的营地的道具分配结果为1个3小时道具和2个2小时道具。将其转化成代码实现如下:

       const MAX = 1000000;
        /**数组对象深拷贝*/
        function copy(list) {
            let obj;
            let isArr = Array.isArray(list);
            let isObj = list != null && list instanceof Object;
            if (isArr) {
                obj = [];
                for (let i = 0; i < list.length; i++) {
                    obj[i] = copy(list[i]);
                }
            } else if (isObj) {
                obj = {};
                for (let i in list) {
                    obj[i] = copy(list[i]);
                }
            } else {
                obj = list;
            }
            return obj;
        }
        //删除无效项
        function check(list) {
            let len = list.length;
            while (len--) {
                if (list[len].count == 0) {
                    list.splice(len, 1);
                }
            }
        }

        function getBest(list, effect) {

            let keys = copy(list);
            check(keys);
            let kinds = keys.length;
            let allEffect = 0;
            for (let i of list) {
                allEffect += i.value * i.count;
            }
            //所有效果总和不比需求来得大,不必计算
            if (allEffect <= effect) {
                return { value: MAX };
            }
            let values = [];
            /**构建一个二位数组表,value为当前的结果值,id为存放道具id组合*/
            for (let i = 0; i <= kinds; i++) {
                values[i] = [];
                for (let j = 0; j <= effect; j++) {
                    values[i][j] = {};
                    values[i][j]["value"] = MAX;
                    values[i][j]["id"] = {};
                    for (let key of list) {
                        values[i][j]["id"][key.id] = 0;
                    }
                }
                values[i][0]["value"] = 0;
            }
            for (let i = 0; i <= effect; i++) {
                values[0][i]["value"] = MAX;
            }
            for (let eff = 1; eff <= effect; eff++) {
                for (let key = 1; key <= kinds; key++) {
                    //如果左侧没有最优解,则当前项不可能有最优解
                    if (values[key][eff - 1].value == MAX) {
                        values[key][eff].value = MAX;
                        continue;
                    }
                    let value = keys[key - 1].value;
                    let id = keys[key - 1].id;
                    let lastItem = values[key - 1][eff];
                    let customItem = values[key][eff];
                    //如果目标值小于当前的道具效果值,将上一个目标结果与当前的效果值做比较,取小
                    //参考 需要目标值为1时的推导
                    if (eff < value) {
                        let value1 = lastItem.value; //目标上一个结果值
                        if (value1 < value) {
                            customItem.value = value1;
                            customItem.id = copy(lastItem.id);
                        } else {
                            customItem.value = value;
                            customItem.id[id]++;
                        }
                        continue;
                    }
                    let leftItem = values[kinds][eff - value];
                    let canUsed = leftItem.id[id] < keys[key - 1].count;

                    //当前项不可用
                    if (!canUsed) {
                        leftItem = copy(values[key - 1][eff - value]);
                        //从旧的结果中查找最优替代解
                        for (let k = eff - value; k <= eff; k++) {
                            for (let l = key - 1; l >= 1; l--) {
                                if (values[l][k].value < leftItem.value) {
                                    leftItem = copy(values[l][k]);
                                }
                            }
                        }
                    }
                    if (leftItem.value == MAX) {
                        customItem.value = MAX;
                        continue;
                    }
                    let value1 = lastItem.value;
                    let value2 = leftItem.value + value;
                    if (value1 < value2) {
                        customItem.value = value1;
                        customItem.id = copy(lastItem.id);
                    } else {
                        customItem.value = value2;
                        customItem.id = copy(leftItem.id);
                        customItem.id[id]++;
                    }

                }
            }
            console.log(values[kinds][effect])
            return values[kinds][effect];
        }
        let list = [
            { id: "a", value: 1, count: 2 },
            { id: "b", value: 2, count: 1 },
            { id: "c", value: 3, count: 2 },
            { id: "d", value: 4, count: 3 },
        ];
        let eff = 16;
        getBest(list, eff);
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容