【问题标题】:Sets of all disjoint pairs所有不相交对的集合
【发布时间】:2015-12-06 06:17:10
【问题描述】:

给定一组{1,2,3,4,5...n}n 元素,我们需要找到所有不相交对的集合。

例如,如果 n=4,则输出为

{(1,2),(3,4)},   {(1,3),(2,4)},   {(1,4),(2,3)}

我什至不知道如何开始。我希望有人能给我一个关于使用哪种算法的建议,可能还有一些实现细节。

【问题讨论】:

  • 举个小n值的例子..
  • 如果 n=4 ,输出将是 {(1,2), (3,4)}, {(1,3),(2,4)},{(1,4) ,(2,3)}
  • 我们可以给你一个想法,而不是整个算法或实现。
  • 是的,即使是一个想法也会有所帮助
  • 我们可以给予任何人决定给予的任何东西。由于该问题与本网站无关(没有给定算法,这实际上是一个数学问题),因此得到良好处理的机会很小。

标签: c algorithm set permutation


【解决方案1】:

编辑:
递归生成(n-1)的Delphi代码!!从 n=2*k 个元素中设置 (1*3*5*7...n-1)

var
  A: TArray<Integer>;

  procedure Swap(i, j: integer);
  var
    t : integer;
  begin
    t := A[i];
    A[i] := A[j];
    A[j] := t;
  end;

  procedure MakePairs(Start: Integer; Pairs: string);
  var
    i: Integer;
  begin
    if Start >= Length(A) then
      Writeln(Pairs)
    else
    for i := Start + 1 to High(A) do begin
      Swap(Start + 1, i); //store used element in the array beginning
      MakePairs(Start + 2, Pairs + Format('(%d,%d)', [A[Start], A[Start + 1]]));
      Swap(Start + 1, i); //get it back
    end;
  end;

begin
  A := TArray<Integer>.Create(1,2,3,4,5,6);
  //be sure that array length is even!!!
  MakePairs(0, '');
  Writeln(PairCount);

输出:

(1,2)(3,4)(5,6)
(1,2)(3,5)(4,6)
(1,2)(3,6)(5,4)
(1,3)(2,4)(5,6)
(1,3)(2,5)(4,6)
(1,3)(2,6)(5,4)
(1,4)(3,2)(5,6)
(1,4)(3,5)(2,6)
(1,4)(3,6)(5,2)
(1,5)(3,4)(2,6)
(1,5)(3,2)(4,6)
(1,5)(3,6)(2,4)
(1,6)(3,4)(5,2)
(1,6)(3,5)(4,2)
(1,6)(3,2)(5,4)
15

加法
也适用于奇数长度数组的变体(奇怪的排序)

  procedure MakePairs(Start: Integer; Pairs: string);
  var
    i: Integer;
    OddFlag: Integer;
  begin
    if Start >= Length(A) then
      Memo1.Lines.Add(Pairs)
    else begin
      Oddflag := (High(A) - Start) and 1;
      for i := Start + OddFlag to High(A) do begin
        Swap(Start + OddFlag, i);
        if OddFlag = 1 then
          MakePairs(Start + 2, Pairs + Format('(%d,%d)', [A[Start], A[Start + 1]]))
        else
          MakePairs(Start + 1, Pairs);
        Swap(Start + OddFlag, i);
      end;
    end;
  end;

对于 (1,2,3,4,5):

(2,3)(4,5)
(2,4)(3,5)
(2,5)(4,3)
(1,3)(4,5)
(1,4)(3,5)
(1,5)(4,3)
(2,1)(4,5)
(2,4)(1,5)
(2,5)(4,1)
(2,3)(1,5)
(2,1)(3,5)
(2,5)(1,3)
(2,3)(4,1)
(2,4)(3,1)
(2,1)(4,3)
15

现在不相关:
如果每一对都应该只出现一次(从你的例子中 n=4 不清楚),那么你可以使用round-robin tournament algorithm

n=4 case example here

【讨论】:

  • 没有每一对不会只出现一次 {1,2,3,4,5,6} 输出将是 {(1,2),(3,4),(5,6 )},{(1,3),(2,4),(5,6)},{(1,4),(2,3),(5,6)},{(1,2)( 3,5)(4,6)} 等等......一个集合的每个元素都必须与另一个集合的每个元素配对
  • 哦,你跳过了 n 奇怪的有趣部分,例如n=5 的输出为 (12)(34),(12)(35),(12)(45),(13)(24),(13)(25),(13)(45),( 14)(23),(14)(25),(14)(35),(15)(23),(15)(24),(15)(34),(23)(45),(24) )(35),(25)(34)
  • @user3386109 我不确定它是否需要(留下一个没有对的元素)
  • 是的,这是有争议的,问题不是很清楚:)
  • @user3386109 为该案例添加了修改
【解决方案2】:

你必须在这里看到模式。

对于{1, 2, 3, 4}

取第一个元素并与右边的所有元素配对。

(1, 2), (1, 3), (1, 4)

取第二个元素并与右边的所有元素配对。

(2, 3), (2, 4)

取第三个元素并与右边的所有元素配对。

(3, 4)

...等等

注意这里的模式。


您需要一个外部循环来遍历元素并逐个选择每个元素。

还有另一个内部循环,用于遍历所选元素右侧的元素,并与每个元素配对。

【讨论】:

  • 所以你要我注意这样的模式,比如组合第一对和最后一对,然后是第二对和第二对,依此类推……比如 (1,2)(3,4); (1,3)(2,4);(1,4)(2,3) ?
  • @DiscoveringNew:这个答案中描述的方法只会找到对,而不是不相交的集合。
  • @MOehm 如果元素不同,它会找到不相交的对。
  • @haris:元素在定义上是不同的,但所需的输出不仅仅是对,而是由 OP 在对问题的评论中阐明的不相交对的集合。 (也许 OP 相应地编辑问题是个好主意。)
  • @MOehm 好的。那他需要举个例子。这有点令人困惑。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-19
  • 2019-05-16
  • 1970-01-01
相关资源
最近更新 更多