Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 通过加或减两个整数之间的最短路径_Algorithm_Math_Numbers_Theory_Equation - Fatal编程技术网

Algorithm 通过加或减两个整数之间的最短路径

Algorithm 通过加或减两个整数之间的最短路径,algorithm,math,numbers,theory,equation,Algorithm,Math,Numbers,Theory,Equation,以下是此问题的描述: 给你两个整数a和b。您希望找到将a转换为b所需的最短操作序列,在每个步骤中,您可以添加或减去5、7或12 例如,如果给定a=-5和b=19,则最短路径为 -5 + 12 + 12 = 19 如果给定1和3,则最短路径为 1 + 7 - 5 = 2 我能想到的解决这个问题的唯一方法就是使用BFS,也许还有更多的修剪。有没有更好的算法可以替代 谢谢 我想你可以看一下电话号码来寻找想法。这个问题相当于获取a-b的号码。或者abs(a-b),因为它是围绕零对称的。我认为这可以很

以下是此问题的描述:

给你两个整数a和b。您希望找到将a转换为b所需的最短操作序列,在每个步骤中,您可以添加或减去5、7或12

例如,如果给定a=-5和b=19,则最短路径为

-5 + 12 + 12 = 19
如果给定1和3,则最短路径为

1 + 7 - 5 = 2
我能想到的解决这个问题的唯一方法就是使用BFS,也许还有更多的修剪。有没有更好的算法可以替代


谢谢

我想你可以看一下电话号码来寻找想法。

这个问题相当于获取a-b的号码。或者
abs(a-b)
,因为它是围绕零对称的。我认为这可以很容易地通过采用。例如,获取23的最快方法是获取
23+5,23-5,23+7,23-7,23+12
23-12
加上一个操作的最快方法。如果你在开始条件下应用几次(成本+5,-5,…是1,其他的是无限的),你将在
O(a-b)
中得到你的答案,你需要解5x+7y+12z=b-a。使得| x |+| y |+| z |最小。也许有一种简单的数学方法。也许这会有所帮助:

让我们从一组有趣的观察开始。正如许多其他人所指出的,目标是找到一些具有整数系数的5x+7y+12z=b-a的线性组合,以使| x |+| y |+| z |最小化。但我们可以利用这三个数字之间的一些非常有趣的联系:

  • 如果我们有一个5x+7y+12z的组合,其中x和y都是正的或都是负的,我们可以抵消一些x和y,以增加相等数量的12s。换句话说,没有最优解在x和y上都有相同的符号,因为我们总是可以使这个解更好
  • 如果我们有一个5x+7y+12z的组合,其中y和z有相反的符号,我们总是可以删除7和12,并添加适当符号的5,以获得更好的解决方案。类似地,如果x和z有相反的符号,我们总是可以删除5和12,并在适当的符号中添加7。这意味着我们永远不需要考虑Z与X或Y具有相同符号的任何解决方案,因为这意味着必须有更好的解决方案。
  • 让我们思考一下(1)和(2)共同告诉我们的内容。(1) 说x和y上的符号不能相同,因为我们总是可以做得更好。(2) 如果x和z有相反的符号,或者y和z有相反的符号,我们总是可以做得更好。总的来说,这意味着

    引理:在最优解中,x、y或z中至少有一个必须为零

    要看到这一点,如果这三个都是非零的,如果x和y有相同的符号,那么我们可以用12s来代替它们,从而使解决方案变得更好。否则,x和y具有相反的符号。因此,如果x和z有不同的符号,那么通过(2)我们可以用更少的7替换它们,否则y和z有不同的符号,通过(2)我们可以用更少的5替换它们

    好的,这看起来真的很棒!这意味着我们只需要求解这三个整数方程,并找出哪一个具有最小的系数和:

    • 5x+7y=b-a
    • 5x+12z=b-a
    • 7y+12z=b-a
    幸运的是,由于gcd(5,7)=gcd(5,12)=gcd(7,12)=1,所有这些方程组都有b-a的任何值的解

    现在,让我们看看如何解这些方程。幸运的是,我们可以使用一些可爱的技巧来大大减少搜索空间。例如,对于5x+7y=b-a,x的值不能在[-6,+6]之外,因为如果是,我们可以用五个7替换其中的七个。这意味着我们可以通过执行以下操作来解决上述方程:

    对于x=-6到+6,通过计算(b-a)-5x,看看5x+7y=b-a是否有一个整数解,并看看它是否可以被7整除。如果是这样,解决问题所需的步骤数由| x |+|((b-a)-5x)/7 |给出

    我们可以使用类似的技巧来求解后两个方程——对于第二个方程,x的范围为-11到+11,对于第三个方程,y的范围也为-11到+11。然后我们可以从三个方程中找出最好的答案,看看答案是什么

    这里有一些伪代码来记录尽可能少的步骤。通过记录使用了哪些解决方案,然后将其扩展到完整路径,可以很容易地修改它以返回这些步骤:

    Let best = infinity
    
    # Solve 5x + 7y = b - a
    for x = -6 to +6:
        if ((b - a) - 5 * x) mod 7 = 0:
            best = min(best, |x| + |((b - a) - 5 * x) / 7|)
    
    # Solve 5x + 12y = b - a
    for x = -11 to +11:
        if ((b - a) - 5 * x) mod 12 = 0:
            best = min(best, |x| + |((b - a) - 5 * x) / 12|)
    
    # Solve 7x + 12y = b - a
    for x = -11 to +11:
        if ((b - a) - 7 * x) mod 12 = 0:
            best = min(best, |x| + |((b - a) - 7 * x) / 12|)
    
    return best;
    
    该算法速度惊人——它只需O(1)个时间,因为求解每三个线性系统所需的迭代次数是一个常数(最多23次)。它只需要O(1)个内存来保存可能的值,我认为在实践中,它可能是您能够编写的最快的算法


    希望这有帮助

    将所有操作组合预先计算成一个哈希映射,然后只需查找答案

    预计算步骤需要时间,但一旦完成,您将在预计算范围内找到答案,即1查找操作

    下面是一个小的JavaScript演示:

    // maximum depth of combos to try
    var MAX = 6;
    // possible operations
    var ops = ["+-5", "+5", "+-7", "+7", "+-12", "+12"];
    // initial hash map of operations->value
    var all = {"+5":5, "+-5":-5, "+7":7, "+-7":-7, "+12":12, "+-12":-12};
    var allcnt = 6; // count combos *not needed*
    // initial hash map of values->operations, plus "0" so we can avoid it
    var unique = {"0": "0", "5":"+5", "-5":"+-5", "7":"+7", "-7":"+-7", "12":"+12", "-12":"+-12" };
    var ready = false;
    // get all useful combinations of ops
    function precalc() {
      var items = [];
      for(var p in all) {
         items.push(p);
      }
      for(var p=0; p<items.length; p++) {
        for(var i=0; i<ops.length; i++) {
          var k = items[p] + ops[i];
          var v = eval(k);
          if(unique[v] == null) {
            unique[v] = k;
            all[k] = v;
            allcnt++;
          }
        }
      }
    }
    // find an answer within the pre-calc'd depth
    function find(a, b) {
      if(ready === false) {
        for(var i=0; i<MAX; i++) precalc();
        ready = true;
      }
      return unique[""+Math.abs(a-b)];
    }
    // test
    find(-5,19);
    
    //要尝试的组合的最大深度
    var MAX=6;
    //可能的操作
    变量运算=[“+-5”、“+5”、“+-7”、“+7”、“+-12”、“+12”];
    //操作的初始哈希映射->值
    var all={“+5”:5,“+-5”:-5,“+7”:7,“+-7”:-7,“+12”:12,“+-12”:-12};
    var allcnt=6;//计数组合*不需要*
    //值->操作的初始哈希映射,加上“0”,这样我们就可以避免它
    var unique={“0”:“0”、“5”:“+5”、“-5”:“+-5”、“7”:“+7”、“-7”:“+-7”、“12”:“+12”、“-12”:“+-12”};
    var ready=false;
    //获取所有有用的操作组合
    函数precalc(){
    var项目=[];
    用于(var p总计){
    推送(p);
    }
    
    对于(var p=0;p预先计算第一个最小范围所需的运算,然后继续添加+12的倍数。