总统座位回溯

时间:2013-12-11 01:27:18

标签: java algorithm backtracking

尽管我很好地掌握了回溯的概念,但是在我面前有一个我无法掌握的问题。我一直无法找到有关此特定问题的任何信息,而且我不知道是否有其他名称。问题是构建一个回溯算法,打印出N个“总统”可以坐在圆桌旁而不坐在同一个人身边两次的座位组合列表。例如,你给它一个输入8,它给你输出,

1 2 3 4 5 6 7 8

1 3 5 2 6 8 4 7

1 4 2 7 5 8 3 6

现在我为简单的游戏(跳棋,n-queens,tic-tac-toe)构建了自己的回溯算法,但是我使用的这些算法都是用空白画布开始的,不需要这种类型的实现。我要求的是一些指导和见解,或链接到这个问题的更多信息,因为所有给出的是关于一页半,主要是谈论组合1 2 3 4如何实际上与1相同4 3 2在这个特殊的问题。这需要使用回溯方法来完成,而这正是让我感到困惑的原因。如果我们能够自由地找到解决方案,我可以很容易地做到。任何帮助表示赞赏。

谢谢!

2 个答案:

答案 0 :(得分:0)

我认为你必须添加有关谁已经回到已经回溯算法状态的人的信息:

  • 你先说,1。您将2放在他旁边,并将此“配对”记录在当前的部分解决方案中。 (字面上只是一对无序的总统ID。实现一对无序数字的简单方法是让该类的构造函数在该对的第一个元素中存储较小的ID,并在第二个元素中存储较大的ID元素。)所以你有一个部分解决方案1 2 …,配对1-2
  • 当您使用完整的解决方案时,将其所有配对添加到“全局”配对列表中。这将在将来的搜索中使用。即如果您获得解决方案1 2 3 4 5 6 7 8,则会保存配对1-22-33-44-55-66-77-81-8
  • 现在,在进行搜索时,您有一个部分解决方案x y z … - 到目前为止坐的最后一位总统是z,此部分解决方案中的配对是x-yy-z。要担任下一任总统,你需要看看每位总统:

    1. 目前尚未就座。 (因此不包括在部分解决方案的配对中。)
    2. 在全局配对中未与z配对。
    3. 如果没有这样的总统,您将丢弃部分解决方案并回溯。

那就是说,我正在这里工作,所以如果我错过任何边缘情况,你应该通过使用简单的暴力实施并比较结果来实际进行双重检查。

答案 1 :(得分:0)

非常粗略的伪代码将如下所示:

global flag // I know it is a bad practice but can't think of a better idea at this point
back (PresidentList, chairNumber, computedList)
if (PresidentList.size() == 0) 
    if (computedList doesn't violate any global distribution)
        add computedList to globalList
        add distirbution of computedList to global distirbution
        set flag;
    else return;
else if (flag is set and chairNumber > 2) return;
else if (flag is set and chairNumber = 2) un set flag; return;
else if (chairNumber == maxChairs-1)
    // at this point there should be only one president in PresidentList
    if (PresidentList.back() can sit with computedList.back() and computedList.front())
        remove president from PreseidentList, add president to computedList
        back(PresidenList, chairNumber+1,computedList)
    else return;
else
    for every president in PresidentList
        if (president can sit with computedList.back()) 
             remove president from PreseidentList, add president to computedList
             back(PresidentList,chairNumber+1,computedList);

你总是根据全球分布变量检查总统是否可以坐在其他总统附近。

在main函数中,只运行一个PresidentList的循环,该循环将以{1}}开始,该总统作为第一个。

标志的概念如下:当您向全局列表添加分发和列表时,back已经运行了许多分支,这些分支与您刚刚添加的列表具有相同的前缀,因此已经不好了。要关闭所有这些列表,强制后退停止分支并返回到可以在列表中设置新的第二个元素进行计算的点,即如果函数的最后一个back分支则返回循环。 / p>