在回溯中记住列表

Remembering Lists in backtracking

提问人:MrKhonsu 提问时间:6/17/2023 最后编辑:Joris SchellekensMrKhonsu 更新时间:8/21/2023 访问量:56

问:

我正在研究一个问题,该问题要求我生成一个包含所有差异值的数组。回溯自然似乎是这里使用的方法,但我在回溯的基本原理方面存在一些问题。 每个节点上都有一个 choiceList,我必须从中选取一个元素并测试条件。

但是假设条件失败(在某个叶节点上)并且我回溯,我如何记住那个阶段?choiceList

我的代码:

def arrayGen(n,N,proto,choiceList,i):
    proto[-1] = N

    if None not in proto:
        lst = diffChecker(proto)
        if 0 in lst or 1 in lst: #now we backtrack
            print(f"{proto} is not a solution\n")
            return
        else:
            print(f"{proto} is a solution\n")

            return

    if not choiceList: #choicelist is empty
        print(f"{proto} contains None\n")
        return


    if proto[i] is None:
        proto[i] = choiceList[0]
        choiceList.pop(0)
        arrayGen(n,N,proto,choiceList,i+1)
        proto[i] = None
        arrayGen(n,N,proto,choiceList,i)
    else:
        arrayGen(n,N,proto,choiceList,i+1)

[子空间的照片,如果它有帮助][1]

[1]:https://i.stack.imgur.com/FC7DP.jpg 盒装列表是 choiceLists。

我遇到的主要问题是在 [0,1,2,5,6] 节点回溯后,ChoiceList 变为空。我希望它恢复到当时的样子。因此,当从 [0,1,2,5,6] 回溯到 [0,1,2,None,6] 时,它应该检测到由于 choiceList 为空,因此此处的所有可能组合都已被探索,并且应该再次回溯到 [0,1,None,None,6],这里 choiceList 应该恢复为 {2,3,4,5} - {2} = {3,4,5},因为到目前为止{2}一直使用。

我意识到我没有说得很清楚,我很抱歉。我需要的是有关如何在此类问题中执行回溯的见解?

编辑- diffChecker 函数(检查相关条件的成功/失败)

def diffChecker(lst):
    result = [0]*(lst[-1]+1)
    dontCount = set()
    result[0] = 2
    result[-1] = 2
    for i in range(1,lst[-1]):#diff_Values
        dontCount = set()
        for j in lst:
            if j == None:
                continue
            if((j + i) in lst and frozenset((j,j+i)) not in dontCount):
                result[i] += 1
                dontCount.add(frozenset((j,j+i)))
            elif((j-i) in lst and frozenset((j,j-i)) not in dontCount):
                result[i] += 1
                dontCount.add(frozenset((j,j-i)))
    return result

驱动程序代码-

#driver/main code-
n = int(input("Enter array size: "))
N = n+1 # dynamic upper limit
proto = [None]*n #length of resultant array is fixed
proto[0] = 0 #first element is always 0
proto[-1] = N
diff_table = [0]*(N+1)
diff_table[-1] = 2 #in actuality it is 1, but for efficiency purposes we've put = 2
diff_table[0] = 2
current_diff = 1 # since diff val of 0 is already present twice - (0-0) & (N-N)
choiceList = []
for i in range(1,N):
    choiceList.append(i)
i = 0
arrayGen(n,N,proto,choiceList,i)

示例输入/输出方案(当前)-

Enter array size: 5
#now, we try to generate all array combinations that satisfy the diffChecker function from this via backtracking

[0, 1, 2, 3, 6] is not a solution

[0, 1, 2, 4, 6] is not a solution


[0, 1, 2, 4, 6] is not a solution

[0, 1, 2, 5, 6] is not a solution


[0, 1, 2, None, 6] contains None

[0, 1, None, None, 6] contains None
#from this part on, the code should not backtrack again. Refer to the attached picture on how exactly I'm trying to fill up the None spots

#expected- [0,1,3,None,None,6] ->(advance) [0,1,3,4,None,6] ->....

[0, None, None, None, 6] contains None
python 数组 算法 语言无关的 回溯

评论

0赞 Stef 6/17/2023
老实说,与其他语言相比,我一直发现 python 在回溯方面非常糟糕。python 处理变量的方式与大多数其他语言不同,特别是对于回溯,它可能非常烦人。
0赞 trincot 6/17/2023
我不清楚该功能的意图是什么。是否可以添加在具体但较小的示例输入上调用此函数的驱动程序代码?你能指出它的预期输出是什么,以及你得到什么吗?您能否提供函数的定义,以便我们可以实际运行您的代码?diffChecker
0赞 MrKhonsu 6/17/2023
这@trincot有帮助?请仔细研究,谢谢
0赞 trincot 6/17/2023
感谢您添加更多代码,但我完全不知道这段代码应该解决什么问题。我完全不明白在做什么,所以我会传递这个问题。diffChecker
0赞 MrKhonsu 6/17/2023
@trincot啊没问题。将 diffChecker 视为检查是接受还是拒绝叶解决方案的某个函数怎么样?我面临的问题是执行回溯

答:

0赞 Matt Timmermans 8/21/2023 #1

基本上有两种策略可以记住以前的状态以进行回溯:

  1. 不要修改状态。相反,将状态的全新副本传递到下一个级别。当状态小而简单时,这就是你所做的。

  2. 在将状态传递到下一级别之前对其进行修改,但请记住消信息并在回溯时撤消修改。当状态太大或太复杂而无法每次都制作新副本时,您会这样做。

您可以针对该州的不同部分混合和匹配这些方法。如果看起来您应该使用撤消策略进行数组修改:

    if proto[i] is None:

        # modify state and remember undo information
        protoUndo = proto[i]
        proto[i] = choiceList[0]
        choiceListUndo = choiceList.pop(0)

        # pass state to next level
        arrayGen(n,N,proto,choiceList,i+1)
        proto[i] = None
        arrayGen(n,N,proto,choiceList,i)

        # undo modifications
        proto[i] = protoUndo
        choiceList.insert(0, choiceListUndo)
    else:
        arrayGen(n,N,proto,choiceList,i+1)