zoukankan      html  css  js  c++  java
  • 面试题:金矿问题-动态规划

    面试题:金矿问题-动态规划

    • 很久很久以前,有一位国王拥有5座金矿,每座金矿的黄金储量不同,需要参与挖掘的工人人数也不同。例如有的金矿储量是500kg黄金,需要5个工人来挖掘;有的金矿储量是200kg黄金,需要3个工人来挖掘……
    • 如果参与挖矿的工人的总数是10。每座金矿要么全挖,要么不挖,不能派出一半人挖取一半的金矿。要求用程序求出,要想得到尽可能多的黄金,应该选择挖取哪几座金矿?

    递归求解

    // 时间复杂度O(2^n)
    function getBestGold(workers, canSelectGold, needWorkersArray, goldCountArray) {
        // 人用完或金矿挖完停止递归
        if (workers === 0 || canSelectGold === 0) {
            return 0;
        }
        // 如果
        if (workers < needWorkersArray[canSelectGold - 1]) {
            return getBestGold(workers, canSelectGold - 1, needWorkersArray, goldCountArray)
        }
        return Math.max(
            getBestGold(workers, canSelectGold - 1, needWorkersArray, goldCountArray),
            getBestGold(workers - needWorkersArray[canSelectGold - 1], canSelectGold - 1, needWorkersArray, goldCountArray) + goldCountArray[canSelectGold - 1]
        )
    }
    
    let workers = 10;// 总人数
    let needWorkersArray = [5, 5, 3, 4, 3];// 每个金矿所需人数
    let goldCountArray = [400, 500, 200, 300, 350];// 每个金矿储量
    // let res = getBestGold(workers, goldCountArray.length, needWorkersArray, goldCountArray);
    // console.log(res)
    

    自底向上求解

    • 状态转移方程: n是当前金矿储量,w是当前金矿所需人数 ,p是挖掘金矿所需人数数组,g是金矿储量数组
    • F(n,w) = F(n-1,w) (n>1,w<p[n-1])
    • F(n,w) = max( F(n-1,w),F(n-1,w-p[n-1])+g[n-1]) (n>1,w>=p[n-1])
    • 二维数组表示 ,这个比上一个递归好理解
    // 时间复杂度O(nw)
    function getBestGold2(workers, needWorks, goldArray) {
        let resultArray = []
        // 填充二维数组
        for (let i = 0; i < goldArray.length + 1; i++) {
            resultArray.push([0])
            for (let j = 0; j < workers + 1; j++) {
                let arr = resultArray[i]
                arr.push(0)
            }
        }
        console.log(resultArray)
        // 计算每个位置的值
        for (let i = 1; i <= goldArray.length; i++) {
            for (let j = 1; j <= workers; j++) {
                if (j < needWorks[i - 1]) {
                    resultArray[i][j] = resultArray[i - 1][j]
                } else {
                    resultArray[i][j] = Math.max(resultArray[i - 1][j], resultArray[i - 1][j - needWorks[i - 1]] + goldArray[i - 1])
                }
            }
        }
        console.log(resultArray[goldArray.length][workers])
        return resultArray[goldArray.length][workers]
    }
    
    getBestGold2(workers, needWorkersArray, goldCountArray)// 900
    
    • 表格如下

    优化:只保存一行最大值

    // 时间复杂度O(nw),空间复杂度O(n)
    // 只保存一行最大值
    function getBestGold3(workers,needWorkers,goldArray) {
        let resultArray = new Array(workers+1).fill(0)
        console.log(resultArray)
        // 计算每个位置的值
        // 计算行
        for (let i = 1; i <= goldArray.length; i++) {
            // 计算列,从右向左,人数多挖的金矿肯定多,所以可以避免很多不必要的计算
            // 比如说最后一列大于倒数第二列,那么接下来就不用再计算,直接进入下一行
            for (let j = workers; j >=1; j--) {
                if (j >= needWorkers[i - 1]) {
                    resultArray[j] = Math.max(resultArray[j], resultArray[j - needWorkers[i - 1]] + goldArray[i - 1])
                }
            }
        }
        console.log(resultArray[workers])
        return resultArray[workers]
    }
    getBestGold3(workers, needWorkersArray, goldCountArray)// 900
    

  • 相关阅读:
    mysql中cast() 和convert()的用法讲解
    li内有span需要右浮的问题
    svn检出项目
    vue中的 ref 和 $refs
    for in 循环 和for循环 for of循环
    setInterval()、clearInterval()、setTimeout()和clearTimeout() js计数器方法(还有第三个参数)
    利用history.pushState()实现页面无刷新更新
    函数isNaN() parseFloat() parseInt() Math对象
    一个关于margin-top的问题
    vue 父子组件之间传参
  • 原文地址:https://www.cnblogs.com/songliquan/p/13228369.html
Copyright © 2011-2022 走看看