计算所有可能的和有意义的排列

时间:2014-11-21 07:59:53

标签: c++ algorithm permutation permute

我的问题是某种中国邮递员问题。

我有一个迷宫,程序中有n个代理和n个目标。现在每个代理商必须至少访问一次目标。因此,我必须使用A *算法计算所有目标之间的最短路径,可能是后来的D *。

现在我的问题是计算目标的排列。我的意思是我有一个程序来计算所有可能的排列。但这并不意味着要聪明地了解它们。我的意思是如果我有4个目标,我得到了n!排列(在这个例子中为24)。但是排列1234的路径长度与4321相同。所以我需要升级我的函数以在所有排列中找到对称性,并且只使用A *来获得最小的排列数。

所以这是我目前用来生成所有排列的代码。目前我只是将它们打印出来,但后来我想用一种数组或向量来处理排列,但与我的主要问题相比,它相当简单。

#include <iostream>
#include <algorithm>
#include <iterator>

int main( int argc, char *argv[] )
{
  unsigned int n = atoi( argv[1] );
  unsigned int f[n], *const fn = f + sizeof(f) / sizeof(*f);

  for(int j=0; j<n; j++)
  {
    f[j]=(j+1);
  }

  unsigned int i = 0;

  do
  {
    std::cout << ++i << ". Permutation: ";
    copy(f, fn, std::ostream_iterator<int>(std::cout, " "));;
    std::cout << std::endl;
  }
  while(std::next_permutation(f, fn));

  return 0;
}

1 个答案:

答案 0 :(得分:0)

要跳过对称排列,您可以跳过最后一个节点不如第一个节点的那个:

void show_permutation(std::vector<unsigned int> v)
{
    int i = 0;
    do {
        if (v.back() < v.front()) {
            continue;
        }
        std::cout << ++i << ". Permutation: ";
        copy(v.begin(), v.end(), std::ostream_iterator<unsigned int>(std::cout, " "));
        std::cout << std::endl;
    } while(std::next_permutation(v.begin(), v.end()));
}

Live example