启发式算法详解

NP问题

      了解启发式算法之前,我们需要先了解下启发式算法所使用的场景,启发式算法主要的使用场景是NP问题,例如一维装箱,旅行商问题。这些问题有一个显著的特征:获得准确解需要付出很大的代价,而启发式算法则是利用有限的资源,尽可能的去计算较优解。

解决NP问题的算法

以一维装箱为例,传统的NP问题解法有:

  • 穷举法:穷尽法需要搜索 n! 次,这么搞cpu吃不消;
  • 动态规划:搜索次数是能减少,但是一旦输入的参数较大,创建DP所需的数组可能直接OOM了;
  • 贪心算法:贪心算法的确能获得一个较好的结构,常见的贪心算法有:
    • First-fit:遍历当前箱子,把物品放入第一个能放下该物品的箱子,都放不下则新开一个箱子。
    • Best-fit:对每个物品遍历当前箱子,把物品放入最合适放下该物品的箱子。
    • Worst-fit:对每个物品遍历当前箱子,把物品放入最不合适放下该物品的箱子。

      贪心算法虽然能获取到一个比较好的解,但是上述提到的贪心算法比较依赖于输入顺序,举个栗子,有一堆物品 {14,6,14,6,4,6,6,4},箱子的总容量为30,使用First-fit解得的结果为:{14,6,6,4},{14,6,6,4}。
      如果改变下输入顺序,排个序变成{4,4,6,6,6,6,14,14},结果:{4,4,6,6,6},{6,6,6},{14,14}

启发式算法的诞生

      既然得到最优解需要耗费很多资源,那退而求其次,获取次优解或者以一定概率获取最优解也是能接受的。那么随机改变数组的输入顺序,就有那么一丝希望能获取到最优解或者次优解。

      启发式算法可以这样定义:一个基于直观或经验构造的算法,在可接受的花费(指计算时间和空间)下给出待解决组合优化问题每一个实例的一个可行解,该可行解与最优解的偏离程度一般不能被预计。

第一个版本的启发式算法

第一个版本的启发式算法,乱数搜索,只接受比当前更好的解

    private void getMinBoxes(int[] bins) {
    	// 利用贪心算法计算结果
        int best = fitness.getMinimumBins(bins);
        for (int i = 0; i < 1000; i++) {
            int positionA = random.nextInt(length);
            int positionB = random.nextInt(length);
            int[] temp = Arrays.copyOf(bins, bins.length);
            swap(temp, positionA, positionB);
            int cur = fitness.getMinimumBins(temp);
            if (cur <= best) {
                bins = temp;
                best = cur;
            }
        }
    }

这个最初版本的启发式算法有很多的不足,我们只一味的接受更好的解,而有些时候往往会产生一些局限性,导致最优解无法被找到。

更好的启发式算法

现在诞生的启发式算法都是由第一个版本的启发式算法改良得到的,可以参考后续的文章:

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值