小编典典

BFS用于算术运算

algorithm

用最少的运算将数字m转换为n。允许的运算为1减乘以2。

例如:4和6。答案为2。第一操作:-1-> 4-1 =3。第二操作:*-> 3 * 2 = 6。

我对特定的输入(src = 26,dst = 5)使用BFS方法,这需要花费很长时间。难道我做错了什么?

from queue_class import queue


class node:

    def __init__(self, value, level, parent):
        self.level = level
        self.value = value
        self.parent = parent

    def get_minimum_distance(src, target, q):
        if src == target:
            return 0
        seen_list = []
        data = node(src, 0, -1)
        q.enqueue(data)
        while not q.isempty():
            data = q.dequeue()
            if data == "sentinel":
                break
            if data.value == target:
                # let's print what has got me here
                while data.parent != -1:
                    print(data.value)
                    data = data.parent
                return "finally reached"
            if data.value in seen_list:
                continue
            seen_list.append(data.value)
            # two operations are allowed i.e. -1 and multiplication by 2
            # check if two numbers have opposite sign and if they have
            # then check if the current number being subtracted from is a negative
            # number. If it is, then there is no point subtracting 1 from that
            if ((data.value ^ target) < 0 and data.value > 0) or (data.value ^ target >= 0):
                q.enqueue(node(data.value - 1, data.level + 1, data))
                q.enqueue(node(data.value * 2, data.level + 1, data))
        return -1

q = queue(1 << 20)
print(get_minimum_distance(26, 5, q))

队列实现在这里完成。

感谢Paul:以下是我在python中使用以下代码编写的代码,它可以完美运行。

def get_minimum_operations(src, dst):
    step = 0
    operations = []
    if src == dst:
        return 0
    if dst < src:
        return src-dst
    while dst > src:
        if dst & 0x01:
            step += 1
            operations.append("-1")
        dst = (dst+1) >> 1
        operations.append("*2")
        step += 1
    for i in range(0, src-dst):
        operations.append("-1")
    return (((src - dst) + step), operations)

src = 38
dst = 100
output = ""
(steps, operations) = get_minimum_operations(src, dst)
print(steps)
try:
    while operations:
        i = operations.pop()
        if i == "*2":
            if output == "":
                output += "(" + str(src) + "*2" + ")"
            else:
                output = "(" + output + "*2" + ")"
        if i == "-1":
            if output == "":
                output += "(" + str(src) + "-1" + ")"
            else:
                output = "(" + output + "-1" + ")"
except IndexError:
    pass
print(output)

阅读 275

收藏
2020-07-28

共1个答案

小编典典

由于指数增长(这里进行了尝试2 ^ (n - 1) to 2^n,其中n是所需步骤的数量),因此BFS并不是完全正确的选择。而是尝试查找用于生成所需数字的逻辑规则。

让我们a在输入号码和b应产生的数量。

有以下三种情况:

  • a == b,这种情况是微不足道的,仅出于完整性考虑而列出
  • a > b,解决方案是将a - b时间减去-1
  • a < b:这是比较棘手的部分

最少数量的运算需要最少数量的乘法和减法。Substractions可以很容易地最小化由于以下事实:(a - 1) * 2 = a * 2 - 2。因此,通过在乘法之前简单地进行减法运算,我们可以轻松地将减法运算的数量减少2的幂。
由于我们只能减去和相乘,因此最小乘法数为min n => a * 2 ^ n >= b
利用这个事实,我们可以确定要减去的金额:s = b - 2 ^ n * a

该实现在伪代码中看起来像这样(无法提供python代码):

//using the same variable-names as above in the description
minOp(int a , int b)
    //find minimum number of multiplications
    int n
    for(n = 0 ; a << n < b ; n++)
        noop

    //find amount to substract
    int s = (a << n) - b

    for(int i = 0 ; i < n ; i++)
        print("(")

    print(a)

    //calculate operations
    while(n > 0)
        //calculate number of times we need to substract here (minimization of substractions)
        while(s >= 1 << n)
            print(" - 1")
            s -= 1 << n

        print(")")

        //divide by two
        print(" * 2")
        n -= 1

    while(s >= 1 << n)
        print(" - 1")
        s -= 1 << n

    print(" = ")
    print(b)

此实现藏汉覆盖情况a == b-与n = 0s = 0-和a > b-与n = 0s = a - b

在上述的Java实现中进行测试运行将产生以下输出:

((((4) 2-1) 2-1)* 2 = 26

上面计算的简化显示了该算法的思想:

((4 * 2 - 1) * 2 - 1) * 2 = 26
(4 * 2 * 2 - 2 - 1) * 2 = 26
4 * 2 * 2 * 2 - 3 * 2 = 26
32 - 6 = 26

感谢@ user3386109的解释:
假设起始值为A,目标值为B。第一步是创建一个从B开始的目标值列表,然后除以2(如有必要,四舍五入)。
。例如,如果B为26,则目标值列表将为26、13、7、4、2、1。如果起始值A是这些目标值中的任何一个,则可以轻松地爬升至目标B(乘以2并在必要时减去1)。如果A不是这些值之一,则从A减去1开始,直到达到这些目标值之一。例如,如果A为6,则需要两个减法才能达到4,然后从4爬到26。如果A为12,则需要五个减法才能达到7,依此类推。显然,如果A大于B,那么您要做的就是减去1直到达到B

2020-07-28