【问题标题】:algorithmic function to create all possible combinations from a list of vectors从向量列表中创建所有可能组合的算法函数
【发布时间】:2016-09-14 15:18:16
【问题描述】:

我有一个 int <List<List<int>> 列表列表,它代表一个方向向量

例如

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

我想用这些向量创建所有可能的路线,这样最终路线就不会创建一个无限循环(结束于自身)

所以:

(1,2)
(1,3)
(2,4)
(3,5)
(4,3)
(5,1)
(1,2,4)
(1,2,4,3)
(1,2,4,3,5)
(1,2,4,3,5,1)
(1,3,5)
(1,3,5,1)
(2,4,3)
(2,4,3,5)
(2,4,3,5,1)
(2,4,3,5,1,2)
(3,5,1)
etc...

我还没有找到一种有效的方法来做这样的事情。

我之前尝试过使用

创建所有可能的组合
    private IEnumerable<int> constructSetFromBits(int i)
    {
        for (int n = 0; i != 0; i /= 2, n++)
        {
            if ((i & 1) != 0)
                yield return n;
        }
    }

  public IEnumerable<List<T>> ProduceWithRecursion(List<T> allValues) 
    {
        for (var i = 0; i < (1 << allValues.Count); i++)
        {
            yield return ConstructSetFromBits(i).Select(n => allValues[n]).ToList();
        }
    }

效果很好,但忽略了问题的方向。

该方法不必是递归的,尽管我怀疑这可能是最明智的方法

【问题讨论】:

    标签: c# algorithm graph-algorithm


    【解决方案1】:

    看起来像广度优先搜索:

    private static IEnumerable<List<int>> BreadthFirstSearch(IEnumerable<List<int>> source) {
      List<List<int>> frontier = source
        .Select(item => item.ToList())
        .ToList();
    
      while (frontier.Any()) {
        for (int i = frontier.Count - 1; i >= 0; --i) {
          List<int> path = frontier[i];
    
          yield return path;
    
          frontier.RemoveAt(i);
    
          // prevent loops
          if (path.IndexOf(path[path.Count - 1]) < path.Count - 1)
            continue;
    
          int lastVertex = path[path.Count - 1];
    
          var NextVertexes = source
            .Where(edge => edge[0] == lastVertex)
            .Select(edge => edge[1])
            .Distinct();
    
          foreach (var nextVertex in NextVertexes) {
            var nextPath = path.ToList();
    
            nextPath.Add(nextVertex);
    
            frontier.Add(nextPath);
          }
        }
      }
    }
    

    测试

    List<List<int>> list = new List<List<int>>() {
      new List<int>() {1, 2},
      new List<int>() {1, 3},
      new List<int>() {2, 4},
      new List<int>() {3, 5},
      new List<int>() {4, 3},
      new List<int>() {5, 1},
    };
    
    var result = BreadthFirstSearch(list)
      .Select(way => string.Format("({0})", string.Join(",", way)));
    
    Console.Write(string.Join(Environment.NewLine, result));
    

    结果:

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

    【讨论】:

    • 谢谢!看起来比我做的要好......我会尝试一下,我会相应地解决
    猜你喜欢
    • 2018-06-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-12
    • 2015-03-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多