简体   繁体   English

总统座位回溯

[英]Presidential Seating Backtracking

I have a problem in front of me that I can't grasp, even though I grasp the concept of backtracking well. 尽管我很好地了解了回溯的概念,但是我面前的问题仍然无法解决。 I have been unable to find any information on this specific problem, and I am unaware if it goes by another name. 我无法找到有关此特定问题的任何信息,并且我不知道它是否使用其他名称。 The problem is to construct a backtracking algorithm that will print out the list of combinations of seating that N number of "presidents" can sit at a round table without sitting next to the same person twice. 问题在于构造一种回溯算法,该算法将打印出N个“总统”可以坐在圆桌旁而不会两次坐在同一个人旁边的座位组合列表。 For example, you give it an input 8, it gives you the output, 例如,您给它输入8,它给您输出,

1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8

1 3 5 2 6 8 4 7 1 3 5 2 6 8 4 7

1 4 2 7 5 8 3 6 1 4 2 7 5 8 3 6

Now I have constructed my own backtracking algorithms for simple games (checkers, n-queens, tic-tac-toe), however these that I have worked with have started with a blank canvas and didn't require this type of implementation. 现在,我已经为简单的游戏(跳棋,n皇后,井字游戏)构建了自己的回溯算法,但是我使用的这些算法都是从空白画布开始的,不需要这种类型的实现。 What I am asking for is a bit of guidance and insight, or links to more information to this problem as all that was given was about a page and a half, mostly talking about how the combination 1 2 3 4 is effectively the same as 1 4 3 2 in this particular problem. 我需要的是一些指导和见识,或者链接到更多有关此问题的信息,因为所提供的内容仅是一页半的内容,主要是讨论1 2 3 4与1的组合实际上如何相同。 4 3 2在这个特定的问题。 This needs to be done using a backtracking method and that's what is making me confused. 这需要使用回溯方法来完成,这让我感到困惑。 If we were give free rein to find solutions I could easily do it. 如果我们可以自由地寻求解决方案,我可以轻松地做到。 Any help is appreciated. 任何帮助表示赞赏。

Thanks! 谢谢!

I'm thinking you'll have to add information about who sat next to who already to the backtracking algorithm state: 我认为您必须将有关谁坐在谁旁边的信息添加到回溯算法状态:

  • You start with, say 1 . 首先说1 You seat 2 next to him, and record this "pairing" in the current partial solution. 您将2坐在他旁边,并在当前局部解决方案中记录此“配对”。 (Literally just an unordered pair of president IDs. An easy way of implementing an unordered pair of numbers is to have the constructor of that class store the smaller ID in the first element of the pair, and the greater ID in the second element.) So you have a partial solution 1 2 … , with the pairing 1-2 . (从字面上看,这是一对无序的总统ID。实现无序的数字对的一种简单方法是让该类的构造函数将较小的ID存储在该对的第一个元素中,将较大的ID存储在第二个元素中。)因此,您有部分解决方案1 2 … ,与1-2配对。
  • When you reach to a complete solution, you add all its pairings to a "global" list of pairings. 当您找到一个完整的解决方案时,可以将其所有配对添加到配对的“全局”列表中。 This will be used in future searches. 这将在以后的搜索中使用。 Ie if you get the solution 1 2 3 4 5 6 7 8 , you save the pairings 1-2 , 2-3 , 3-4 , 4-5 , 5-6 , 6-7 , 7-8 , 1-8 . 即,如果你得到的溶液1 2 3 4 5 6 7 8 ,在保存该配对1-22-33-44-55-66-77-81-8
  • Now, when doing a search, you have a partial solution xyz … – the last president seated so far is z , and the pairings in this partial solution are xy and yz . 现在,当进行搜索时,您有一个局部解xyz … –到目前为止坐下的最后一位主席是z ,并且该局部解中的配对是xyyz To seat the next president, you need to look at every president that's: 要让下一任总统就座,您需要查看每位总统:

    1. Not seated so far. 到目前为止还没有坐下来。 (And thus not included in the partial solution's pairings.) (因此不包括在部分解决方案的配对中。)
    2. Not paired with z in the global pairings. 在全局配对中未与z配对。

    If no such president is available, you discard the partial solution and backtrack. 如果没有这样的总裁,您将放弃部分解决方案并回溯。

That said, I'm working off the top of my head here, so you'd be well advised to actually doublecheck if I missed any edge cases by using a straightforward brute force implementation and comparing the results. 就是说,我在这里努力工作,因此,建议您使用直接的蛮力实施并比较结果,仔细检查是否错过了任何极端情况。

A very rough pseudocode will look like this: 一个非常粗糙的伪代码将如下所示:

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);

You always check if a president can sit near some other president only according to the global distribution variable. 您始终仅根据全球分布变量检查总统是否可以坐在其他总统附近。

In the main function just run a loop for PresidentList that will start back with that president being as the first one. 在主函数中只运行一个循环PresidentList ,将开始back与总统是作为第一个。

The idea of the flag is as follows: when you add a distribution and a list to the global list, back runs already a lot of branches which have the same prefix as the list you just added and hence are already bad. 该标志的思路如下:当您添加一个分布和列表的全局列表, back已经运行了很多具有相同前缀刚才添加的列表,因此已经坏分支。 To close all those lists you force the back to stop branching and return to the point when it can set a new 2nd element in the list to compute ie get back to the loop if the last else branch of the function. 要关闭所有这些列表,您可以强制back停止分支并返回到可以在列表中设置新的第二个元素进行计算的点,即返回到函数的最后else分支的循环。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM