简体   繁体   English

了解餐桌最佳座位算法的问题

[英]Issues with understanding Dining table optimal seating algorithm

I was reading through a problem and was trying to solve this problem. 我正在阅读一个问题,并试图解决这个问题。

You've invited N people over for dinner. 你邀请了N个人吃饭。 Let's say 4. 让我们说4。

You have a circular dinner table and you wish to seat everyone around it. 你有一个圆形餐桌,你希望周围的每个人都坐下来。 Unfortunately, not all of your friends are friends with each other, but you'd like to seat everyone optimally so that as many people as possible are seated next to people they consider friends and not enemies. 不幸的是,并非所有的朋友都是彼此的朋友,但你希望以最佳方式安排每个人,以便让尽可能多的人坐在他们认为是朋友而不是敌人的人旁边。

You've charted everyone's friendships and hatreds in a matrix of size NxN and represented friendships with the integer 1, hatreds with -1, and sheer indifference with 0. 你已经用大小为NxN的矩阵绘制了每个人的友谊和仇恨,并用整数1表示友谊,用-1表示仇恨,用0表示纯粹的冷漠。

[[ 0, 1, 1, 1, 1],    ← yes you like all your friends
 [-1, 0, 1,-1, 0],
 [-1, 1, 0, 1, 0],
 [ 1, 1, 1, 0,-1],
 [ 1, 0, 0,-1, 0]]

Question: 题:

-> Write a Javascript method that computes an optimal seating arrangement as an Array, eg [0,4,2,1,3], for a given input matrix. - >编写一个Javascript方法,为给定的输入矩阵计算最佳座位排列作为数组,例如[0,4,2,1,3]。 (assuming indexes 0 and N-1 are seated adjacently). (假设索引0和N-1相邻)。 What is the time complexity for the solution? 解决方案的时间复杂度是多少? Add thoughts on possible optimizations. 添加有关可能的优化的想法。

I've tried solving this manually however, I didn't understand the question's example [0,4,2,1,3] for the given input matrix. 我已经尝试手动解决这个问题,但我不明白给定输入矩阵的问题示例[0,4,2,1,3]。

Can someone Enlighten me? 有人可以启发我吗?

How did he/she come up with [0,4,2,1,3]? 他/她是如何想出[0,4,2,1,3]的?

Thanks and very much appreciate your time. 谢谢,非常感谢您的时间。

How did he/she come up with [0,4,2,1,3]? 他/她是如何想出[0,4,2,1,3]的?

That permutation certainly isn't the right answer for the example input (see reasoning below), so I think that Emma 's comment above is spot-on: the problem statement is just demonstrating what a "seating arrangement as an Array" should look like in general , not specifically demonstrating the optimal seating arrangement for the example input. 那个排列肯定不是示例输入的正确答案(见下面的推理),所以我认为艾玛上面的评论是正确的:问题陈述只是证明了“作为数组的座位安排”应该是什么样子一般而言 ,没有具体说明示例输入的最佳座位布置。


As for why I say that [0,4,2,1,3] certainly isn't the right answer for the example you've given . 至于为什么我说[0,4,2,1,3]肯定不是你给出的例子的正确答案。 . . I don't completely understand how we decide whether one permutation is better than another, but it's clear that [0,4,1,2,3] is better by any measure. 我不完全理解我们如何决定一个排列是否优于另一个排列,但很明显[0,4,1,2,3]在任何方面都更好。 For both [0,4,2,1,3] and [0,4,1,2,3], the first person (0) likes both neighbors; 对于[0,4,2,1,3]和[0,4,1,2,3],第一个人(0)喜欢两个邻居; the second person (4) is neutral toward both neighbors; 第二个人(4)对两个邻居都是中立的; and the third and fifth people (2 and 3 in the former, 1 and 3 in the latter) each like one neighbor and are neutral toward the other. 第三和第五个人(前者中的2个和3个,后者中的1个和3个)各自像一个邻居并且对另一个是中立的。 The only difference between the two permutations is that in [0,4,2,1,3], the fourth person (1) is neutral toward one neighbor and dislikes the other, whereas in [0,4,1,2,3], the fourth person (2) is neutral toward one neighbor and likes the other. 这两种排列的唯一区别在于,在[0,4,2,1,3]中,第四个人(1)对一个邻居是中立的而不喜欢另一个,而在[0,4,1,2,3] ],第四个人(2)对一个邻居是中立的, 喜欢另一个。 So the latter is obviously superior, no matter whether we consider it more important to increase likes or to decrease dislikes. 所以后者显然是优越的,无论我们是否认为增加喜欢或减少不喜欢更重要。

Checking all possible orders is a classical permutation task even if there might be a more efficient algorithm for this specific problem. 检查所有可能的订单是经典的排列任务,即使可能存在针对此特定问题的更有效的算法。

One optimization can be done by reducing the permutation to array length-1 since in circular orders eg 0,1,2,3,4 and 4,0,1,2,3 (and all further rotations) are the same. 可以通过将置换减少到阵列长度-1来完成一个优化,因为在循环次序中,例如0,1,2,3,4和4,0,1,2,3(以及所有进一步的旋转)是相同的。 You can view the order from you own seat always starting at position 0. 您可以从位置0开始查看自己座位的订单。

(function ()
{
  'use strict';

  let popularity =
  [
    [ 0, 1, 1, 1, 1],   // ← yes you like all your friends
    [-1, 0, 1,-1, 0],
    [-1, 1, 0, 1, 0],
    [ 1, 1, 1, 0,-1],
    [ 1, 0, 0,-1, 0],
  ];

  function permutation(arr)
  {
    let
      l = arr.length,
      perms = []
    ;

    if(l<2)
      return [arr];

    for(let i=0; i<l; i++)
    {
      let
        cpy    = Array.from(arr),
        [perm] = cpy.splice(i, 1)
      ;
      perms.push(...permutation(cpy).map(v => [perm, ...v]));
    }

    return perms;
  }


  let
    keys = Array.from(popularity.keys()).slice(1),
    permutations = permutation(keys),
    rating = permutations.map(v =>
    {
      let
        last = v.length -1,

        // start with our own relationships to the left and right neighbour
        // (each: we like him, he likes us)
        rate =
            popularity [0]       [v[0]]
          + popularity [v[0]]    [0]
          + popularity [0]       [v[last]]
          + popularity [v[last]] [0]
      ;

      for(let i = 0; i<last; i++)
        rate += popularity[v[i]][v[i+1]] + popularity[v[i+1]][v[i]];

      return [rate, [0, ...v]];
    }
  ).sort( (v1, v2) => ( v1[0] === v2[0] ? 0 : (v1[0] > v2[0] ? -1 : 1))  );

  console.log(rating);

})();

output: 输出:

[ [ 8, [ 0, 4, 1, 2, 3 ] ],
  [ 8, [ 0, 3, 2, 1, 4 ] ],
  [ 6, [ 0, 3, 1, 2, 4 ] ],
  [ 6, [ 0, 4, 2, 1, 3 ] ],
  [ 4, [ 0, 1, 4, 2, 3 ] ],
  [ 4, [ 0, 1, 2, 3, 4 ] ],
  [ 4, [ 0, 4, 1, 3, 2 ] ],
  [ 4, [ 0, 1, 3, 2, 4 ] ],
  [ 4, [ 0, 2, 3, 1, 4 ] ],
  [ 4, [ 0, 3, 2, 4, 1 ] ],
  [ 4, [ 0, 4, 2, 3, 1 ] ],
  [ 4, [ 0, 4, 3, 2, 1 ] ],
  [ 2, [ 0, 3, 4, 2, 1 ] ],
  [ 2, [ 0, 3, 1, 4, 2 ] ],
  [ 2, [ 0, 2, 4, 1, 3 ] ],
  [ 2, [ 0, 4, 3, 1, 2 ] ],
  [ 2, [ 0, 3, 4, 1, 2 ] ],
  [ 2, [ 0, 1, 2, 4, 3 ] ],
  [ 2, [ 0, 2, 1, 4, 3 ] ],
  [ 2, [ 0, 2, 1, 3, 4 ] ],
  [ 0, [ 0, 1, 4, 3, 2 ] ],
  [ 0, [ 0, 2, 3, 4, 1 ] ],
  [ -2, [ 0, 1, 3, 4, 2 ] ],
  [ -2, [ 0, 2, 4, 3, 1 ] ] ]

As we can see, there still are reversed permutations combined with yourself (0) having the same rating of course. 正如我们所看到的,仍有反向排列与自己(0)相结合,当然具有相同的评级。 Eleminating mirrored orders, ie reversed permutations, would be another optimization. 重新映射镜像订单,即反向排列,将是另一种优化。

I did this for demonstration in single steps to have a more readable code facing single problems step by step. 我这样做是为了演示,只需要一步一步地解决单个问题的可读代码。 You could refactor the rating calculation directly into the permutation algorithm. 您可以将评级计算直接重构为置换算法。

Properly calculating the time complexity does not seem to be that easy. 正确计算时间复杂度似乎并不那么容易。 Please read the discussion in the comments below. 请阅读以下评论中的讨论。

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

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