NaC*_*aCl 2 c++ algorithm boost stl c++11
让我们说我们有一些数字0 to n,我们想要争夺那些规模,s并希望看到每一种可能的组合.
所以排列的数量恰好等于s! * n!/(s!*(n-s)!).
带n = 3和的示例s = 3:
0 1 2 | 0 1 3 | 0 2 1 | 0 2 3 | 0 3 1 | 0 3 2 | 1 0 2 | 1 0 3 | 1 3 2
1 2 3 | 1 2 0 | 1 3 0 | 2 0 1 | 2 1 0 | 2 0 3 | 2 3 0 | 2 3 1 | 2 1 3
3 0 1 | 3 1 0 | 3 0 2 | 3 2 0 | 3 1 2 | 3 2 1
Run Code Online (Sandbox Code Playgroud)
使用boost/stl实现这一目标是否顺利?
#include <algorithm>
#include <vector>
#include <iterator>
#include <iostream>
void dfs(int depth, int s, int i, std::vector<int>& c, const std::vector<int>& v)
{
if (depth == s)
{
// base case: all chosen elements are in v, so we print
// all permutations of v
do
{
std::copy(c.begin(), c.end(), std::ostream_iterator<int>(std::cout, " "));
std::cout << "| ";
}
while (std::next_permutation(c.begin(), c.end()));
}
else
{
// regular case: loop and recurse, which effectively creates an
// n-dimensional for loop.
// This is the classic approach to finding the
// Cartesian product of N vectors or all combinations of elements.
for (int j = i + 1; j < (int)v.size(); ++j)
{
c.push_back(v[j]);
dfs(depth + 1, s, j, c, v);
c.pop_back();
}
}
}
Run Code Online (Sandbox Code Playgroud)
int main()
{
std::vector<int> v{ 0, 1, 2, 3 };
std::sort(v.begin(), v.end());
v.erase(std::unique(v.begin(), v.end()), v.end());
std::vector<int> c;
const int length = 3;
dfs(0, length, -1, c, v);
}
Run Code Online (Sandbox Code Playgroud)
输出:
0 1 2 | 0 2 1 | 1 0 2 | 1 2 0 | 2 0 1 | 2 1 0 | 0 1 3 | 0 3 1 | 1 0 3 |
1 3 0 | 3 0 1 | 3 1 0 | 0 2 3 | 0 3 2 | 2 0 3 | 2 3 0 | 3 0 2 | 3 2 0 |
1 2 3 | 1 3 2 | 2 1 3 | 2 3 1 | 3 1 2 | 3 2 1
Run Code Online (Sandbox Code Playgroud)
以下是使用TC在评论中引用的链接的代码(http://howardhinnant.github.io/combinations.html):
#include "../combinations/combinations"
#include <iostream>
#include <vector>
int
main()
{
std::vector<int> v{0, 1, 2, 3};
typedef std::vector<int>::iterator Iter;
for_each_permutation(v.begin(), v.begin()+3, v.end(),
[](Iter f, Iter l)
{
for (; f != l; ++f)
std::cout << *f << ' ';
std::cout << "| ";
return false;
}
);
std::cout << '\n';
}
0 1 2 | 0 2 1 | 1 0 2 | 1 2 0 | 2 0 1 | 2 1 0 | 0 1 3 | 0 3 1 | 1 0 3 | 1 3 0 | 3 0 1 | 3 1 0 | 0 2 3 | 0 3 2 | 2 0 3 | 2 3 0 | 3 0 2 | 3 2 0 | 1 2 3 | 1 3 2 | 2 1 3 | 2 3 1 | 3 1 2 | 3 2 1 |
Run Code Online (Sandbox Code Playgroud)
这个库的一个显着优点std::next_permutation是被置换的元素不需要进行排序,甚至也不需要低于可比性.例如:
#include "../combinations/combinations"
#include <iostream>
#include <vector>
enum class color
{
red,
green,
blue,
cyan
};
std::ostream&
operator<< (std::ostream& os, color c)
{
switch (c)
{
case color::red:
os << "red";
break;
case color::green:
os << "green";
break;
case color::blue:
os << "blue";
break;
case color::cyan:
os << "cyan";
break;
}
return os;
}
int
main()
{
std::vector<color> v{color::blue, color::red, color::cyan, color::green};
typedef std::vector<color>::iterator Iter;
for_each_permutation(v.begin(), v.begin()+3, v.end(),
[](Iter f, Iter l)
{
for (; f != l; ++f)
std::cout << *f << ' ';
std::cout << "| ";
return false;
}
);
std::cout << '\n';
}
Run Code Online (Sandbox Code Playgroud)
蓝红色青色| 蓝青红| 红蓝青色| 红青色蓝| 青色蓝色红色| 青色红色蓝色| 蓝红绿| 蓝绿红| 红蓝绿| 红绿蓝| 绿蓝红| 绿色红色蓝色| 蓝绿青绿| 蓝绿色青色| 青色蓝绿色| 青色绿色蓝色| 青蓝青色| 绿色青色蓝色| 红绿青绿| 红绿青色| 青红色绿色| 青绿色红色| 绿色红色青色| 绿色青色红|