座位安排算法

时间:2015-04-21 19:58:50

标签: algorithm

让我来描述一下我的项目模块的问题:

我有一个容量为50的房间。

10行5列。

我有6种不同的口味,每种口味都有无限量的元素。

我需要制作一个座位计划,以便附近没有相同味道的人(正面 - 背面 - 对角线)。

我可以用什么算法来解决这个问题?

如果可能,请描述算法的步骤。

3 个答案:

答案 0 :(得分:1)

<强>算法

对于这个具体的例子,你可以使用贪心算法。迭代行和列,并在每个座位设置任何不会与已经坐着的味道冲突的味道。

<强>证明

xxxxxxxxxx
xxxxxxxxxx
xxxo......
..........
..........

x - already seated
o - currently seating
. - empty

让我们说我们一行一行,从左到右依次迭代。当我们正在建造新的座位时,这个地方最多有4个已经坐过的邻居(请看上面的图片)。由于我们有6种口味,因此总会存在一种口味,这与其他口味不同。对于我们制作的每个座位都是如此,我们可以填充所有50个空间。

<强>概括

对于一般价值观,这个问题可能相当棘手,我甚至敢说NP难。

答案 1 :(得分:1)

一组很好的算法是graph coloring,特别是顶点着色算法。您需要将椅子视为所有相邻椅子边缘的顶点。

答案 2 :(得分:0)

给定的问题是Constraint Satisfaction Problem。特别是(使用术语here):

  1. 变量集X由座位组成(在您的情况下,我们有50个座位对应一组50个变量,每个座位一个)
  2. 域值集D是一组50个域(每个变量1个),每个域包含一组6个值(6种不同的口味)。
  3. 约束集合如下C1 := (X[0,0] != X[0,1]); C2 := (X[0,0] != X[1,0]); C3 := (X[0,0] != X[1,1])等等。
  4. 我个人建议使用Forward Checking以降低复杂性。

    由此产生的算法(没有回滚赋值的简化版本,因为这个特定问题不需要)看起来像这样:

    initialize_domains_for_each_variable;   // set the 6 available flavours
    
    for(int i = 0; i < 10; i++){
        for(int j = 0; j < 5; j++){
            seats[i,j].flavour = seats[i,j].possible_flavours[0];
            // look ahead and eliminate possible conflicts
            remove_this_flavour_from_surrounding_seats_possible_flavours;
        }
    }
    

    这样做会确保不会产生任何冲突,因为每个座位至少有2种可用口味。我们从左到右,从上到下访问座位,因此对于每个座位,我们必须检查哪个分配与先前完成的分配不冲突。在一般情况下,我们将:

    seat[i,j].available_flavours = available_flavours - seat[i-1,j+1].flavour - seat[i-1,j].flavour - seat[i-1,j-1].flavour - seat[i,j-1].flavour
    

    有2个项目。在矩阵的边框中,您将拥有更多可用的风格,因为它可能冲突的项目是2(在左边框的情况下),3(在右边框不在第一行的情况下)或1(在右上角元素的情况下,第一行的右边界。)

    请注意,使用上述算法只会使用5种口味(最低限度)。如果你有必要使用6种口味,你将不得不调整算法。