递归 人气到达指定人气需要的最少花费

125 阅读1分钟

题目

人气一开始是一个偶数,目标也是一个偶数,每次点赞会让人气+2,花费x,送礼物会让人气*2,花费y,点踩会让人气-2,花费z,求最少的花费数量,x、y、z由系统输入

  • 和找零钱问题相似的另一种递归方式,该方式递归需要手动设置更多的base case终止条件
  • 递归规则,三种方式递归实现遍历每一种选择,但是因为存在 -2 的递归,使得之前递归 f(2)依赖的后序条件可能会和f(2)重复造成无限递归,所以要设置很多终止条件
    // 人气+2方式
    let p1 = process(
      preMoney + add,
      aim,
      add,
      times,
      del,
      cur + 2,
      limitAim,
      limitCoin
    );

    // 人气-2方式
    let p2 = process(
      preMoney + del,
      aim,
      add,
      times,
      del,
      cur - 2,
      limitAim,
      limitCoin
    );

    // 人气*2方式
    let p3 = process(
      preMoney + times,
      aim,
      add,
      times,
      del,
      cur * 2,
      limitAim,
      limitCoin
    );
function main(add, times, del, start, end) {
  return process(
    0,
    end,
    add,
    times,
    del,
    start,
    end * 2, // 人气边界
    ((end - start) / 2) * add //平凡解边界
  );
  function process(preMoney, aim, add, times, del, cur, limitAim, limitCoin) {
    // 每次点赞+2,一定能达到的最差解
    if (preMoney > limitCoin) {
      return Infinity;
    }

    if (cur < 0) {
      return Infinity;
    }
    // 人气超高2倍手动终止
    if (cur > limitAim) {
      return Infinity;
    }

    if (aim === cur) {
      return preMoney;
    }

    let min = Infinity;

    // 人气+2方式
    let p1 = process(
      preMoney + add,
      aim,
      add,
      times,
      del,
      cur + 2,
      limitAim,
      limitCoin
    );
    if (p1 !== Infinity) {
      min = p1;
    }

    // 人气-2方式
    let p2 = process(
      preMoney + del,
      aim,
      add,
      times,
      del,
      cur - 2,
      limitAim,
      limitCoin
    );

    if (p2 !== Infinity) {
      min = Math.min(min, p2);
    }

    // 人气*2方式
    let p3 = process(
      preMoney + times,
      aim,
      add,
      times,
      del,
      cur * 2,
      limitAim,
      limitCoin
    );

    if (p3 !== Infinity) {
      min = Math.min(min, p3);
    }

    return min;
  }
}