如果我们 select 来自每个 Y 向量的一个值,则 X 数的每一种组合都是可能的
Every combination of X numbers possible if we select one value from each of Y vectors
如果这个问题有一个正式的名称(或者这是一个重复的问题,我还没有找到合适的问题来查看)然后指出我实际上应该搜索的内容也将不胜感激!但是,我还没有找到任何关于这个特定问题的讨论或方法。
我尽量让问题简单明了,如果有更多详细信息,请告诉我。
假设我们有四个随机长度的整数向量:
std::vector<int> v1 {1, 7, 5, 2};
std::vector<int> v2 {4, 2, 1};
std::vector<int> v3 {1, 9, 4, 6, 4, 1, 2};
std::vector<int> v4 {9, 4};
在这四个向量中,我需要生成所有可能的组合,其中我们一次只从每个源向量 (v1 - v4) select 生成一个整数。结果应该是我们从源向量中生成每个可能的 N 长度数字,其中 N = 源向量的数量(在本例中为 4)。
一些可能的组合很容易生成,例如 select 仅从每个源向量中提取第一个数字:
1 4 1 9
选择每个源向量的最后一个数字:
2 1 2 4
我遇到的问题是生成每一个可能的组合。我需要每个可能的 N 长度数字,这些数字可以通过组合来自 4 个源向量中的每一个的一个整数来创建。
谢谢!
这是一个包含任意数量输入向量的答案:
将索引配置视为一个数字,由不同数字系统中的数字组成。
然后考虑计算一组索引,就像在某些数字系统中计算一个常规数字一样。
例如,对于大小为 3 5 2 5 的四个向量,索引集 0 2 1 4 将导致 0 3 0 0。
对于以下代码,我假设您的向量是在另一个向量中给出的,即 vector<vector<int> >
这里有一个 class 用于索引:
class Indices {
private:
vector<size_t> indices;
vector<size_t> maximal_sizes;
bool _max_reached;
public:
Indices(const vector<vector<int> >& vectors) : indices(vectors.size(), 0), maximal_sizes(vectors.size()), _max_reached(false) {
for(size_t i = 0; i < vectors.size(); i++){
maximal_sizes[i] = vectors[i].size();
}
}
const size_t& operator[] (const size_t i) const { return indices[i]; }
bool max_reached() const { return max_reached; }
void count_up() {
size_t current = 0;
while(current < indices.size()){
indices[current]++;
if(indices[current] >= maximal_sizes[current]){
indices[current] = 0;
current++;
} else {
return;
}
}
_max_reached = true;
}
}
(将其拆分为 header 和来源)
并像
一样使用它
inline void print(const vector<vector<int> >& vectors, const Indices& indices){
for(size_t i = 0; i < vectors.size(); i++){
cout << vectors[i][Indices[i]] << " ";
}
cout << endl;
}
void all_combinations(const vector<vector<int> >& vectors){
Indices indices(vectors);
while(not indices.max_reached()){
print(vectors, indices);
indices.count_up();
}
}
(可能不完全是这样的功能,但你明白了。另外,我认为 Indices
的描述性不够,但现在想不出一个好的短名称。 max_reached 机械师有点烦我,看起来不优雅。如果有人有改进这个的想法,我很想听听。)
您确实在描述您的集合 Cartesian product。就像普通的数字乘积一样,这是对两个事物的运算,但它可以连续应用于两个以上的事物:
A x B x C x D = A x (B x (C x D))
该结构是理解问题的关键。您可以将其分解为递归子问题,每个子问题只涉及两个集合。这样你就可以处理任意数量的集合。
解题的程序也可以是递归的,也可以是迭代的。以下是使用 vector<int>
表示的集合的 lists 的半优化递归解决方案。给定一个集合列表
A, ...
它计算两个事物的笛卡尔积:A,以及其余集合的笛卡尔积:
A x (...)
您可以重新安排此过程以从基本情况开始向上,即 ((D x C) x B) x A。这样您就可以只使用循环而不是递归调用。但是思考问题的递归结构是很好的整理思路。
void cartesian_product( list< vector<int> > sets, list< vector<int> >& product) {
if ( sets.empty() )
return;
// get first set
auto& s = sets.front();
// base case
if ( ++begin( sets ) == end( sets ) ) {
for ( auto k : s ) {
product.push_back( { k } );
}
return;
}
// get cartesian product of the rest of the sets
cartesian_product( list< vector<int> >( ++begin( sets ), end( sets ) ), product );
// make additional copies of product and append each element of first set to them
list< vector<int> > additions;
for ( auto k = ++begin( s ); k != end( s ); ++k ) {
list< vector<int> > ad = product;
for ( auto& x : ad ) {
x.push_back( *k );
}
additions.splice( end( additions ), ad );
}
// append the first element of the first set to the original product
for ( auto& x : product ) {
x.push_back( s.front() );
}
// append the additions to the final product
product.splice( end( product ), additions );
return;
}
这是程序的其余部分:
#include <cassert>
#include <iostream>
#include <list>
#include <vector>
using std::vector;
using std::list;
using std::cout;
using std::endl;
void cartesian_product( list< vector<int> > sets, list< vector<int> > &product);
int main( int argc, char *argv[] ) {
list< vector<int> > sets = {
{1, 7, 5, 2},
{4, 2, 1},
{1, 9, 4, 6, 4, 1, 2},
{9, 4}
};
list< vector<int> > product;
cartesian_product( sets, product );
for ( auto& x : product ) {
cout << "{ ";
for ( auto k : x ) {
cout << k << " ";
}
cout << "}" << endl;
}
}
如果这个问题有一个正式的名称(或者这是一个重复的问题,我还没有找到合适的问题来查看)然后指出我实际上应该搜索的内容也将不胜感激!但是,我还没有找到任何关于这个特定问题的讨论或方法。
我尽量让问题简单明了,如果有更多详细信息,请告诉我。
假设我们有四个随机长度的整数向量:
std::vector<int> v1 {1, 7, 5, 2};
std::vector<int> v2 {4, 2, 1};
std::vector<int> v3 {1, 9, 4, 6, 4, 1, 2};
std::vector<int> v4 {9, 4};
在这四个向量中,我需要生成所有可能的组合,其中我们一次只从每个源向量 (v1 - v4) select 生成一个整数。结果应该是我们从源向量中生成每个可能的 N 长度数字,其中 N = 源向量的数量(在本例中为 4)。
一些可能的组合很容易生成,例如 select 仅从每个源向量中提取第一个数字:
1 4 1 9
选择每个源向量的最后一个数字:
2 1 2 4
我遇到的问题是生成每一个可能的组合。我需要每个可能的 N 长度数字,这些数字可以通过组合来自 4 个源向量中的每一个的一个整数来创建。
谢谢!
这是一个包含任意数量输入向量的答案:
将索引配置视为一个数字,由不同数字系统中的数字组成。 然后考虑计算一组索引,就像在某些数字系统中计算一个常规数字一样。 例如,对于大小为 3 5 2 5 的四个向量,索引集 0 2 1 4 将导致 0 3 0 0。
对于以下代码,我假设您的向量是在另一个向量中给出的,即 vector<vector<int> >
这里有一个 class 用于索引:
class Indices {
private:
vector<size_t> indices;
vector<size_t> maximal_sizes;
bool _max_reached;
public:
Indices(const vector<vector<int> >& vectors) : indices(vectors.size(), 0), maximal_sizes(vectors.size()), _max_reached(false) {
for(size_t i = 0; i < vectors.size(); i++){
maximal_sizes[i] = vectors[i].size();
}
}
const size_t& operator[] (const size_t i) const { return indices[i]; }
bool max_reached() const { return max_reached; }
void count_up() {
size_t current = 0;
while(current < indices.size()){
indices[current]++;
if(indices[current] >= maximal_sizes[current]){
indices[current] = 0;
current++;
} else {
return;
}
}
_max_reached = true;
}
}
(将其拆分为 header 和来源)
并像
一样使用它inline void print(const vector<vector<int> >& vectors, const Indices& indices){
for(size_t i = 0; i < vectors.size(); i++){
cout << vectors[i][Indices[i]] << " ";
}
cout << endl;
}
void all_combinations(const vector<vector<int> >& vectors){
Indices indices(vectors);
while(not indices.max_reached()){
print(vectors, indices);
indices.count_up();
}
}
(可能不完全是这样的功能,但你明白了。另外,我认为 Indices
的描述性不够,但现在想不出一个好的短名称。 max_reached 机械师有点烦我,看起来不优雅。如果有人有改进这个的想法,我很想听听。)
您确实在描述您的集合 Cartesian product。就像普通的数字乘积一样,这是对两个事物的运算,但它可以连续应用于两个以上的事物:
A x B x C x D = A x (B x (C x D))
该结构是理解问题的关键。您可以将其分解为递归子问题,每个子问题只涉及两个集合。这样你就可以处理任意数量的集合。
解题的程序也可以是递归的,也可以是迭代的。以下是使用 vector<int>
表示的集合的 lists 的半优化递归解决方案。给定一个集合列表
A, ...
它计算两个事物的笛卡尔积:A,以及其余集合的笛卡尔积:
A x (...)
您可以重新安排此过程以从基本情况开始向上,即 ((D x C) x B) x A。这样您就可以只使用循环而不是递归调用。但是思考问题的递归结构是很好的整理思路。
void cartesian_product( list< vector<int> > sets, list< vector<int> >& product) {
if ( sets.empty() )
return;
// get first set
auto& s = sets.front();
// base case
if ( ++begin( sets ) == end( sets ) ) {
for ( auto k : s ) {
product.push_back( { k } );
}
return;
}
// get cartesian product of the rest of the sets
cartesian_product( list< vector<int> >( ++begin( sets ), end( sets ) ), product );
// make additional copies of product and append each element of first set to them
list< vector<int> > additions;
for ( auto k = ++begin( s ); k != end( s ); ++k ) {
list< vector<int> > ad = product;
for ( auto& x : ad ) {
x.push_back( *k );
}
additions.splice( end( additions ), ad );
}
// append the first element of the first set to the original product
for ( auto& x : product ) {
x.push_back( s.front() );
}
// append the additions to the final product
product.splice( end( product ), additions );
return;
}
这是程序的其余部分:
#include <cassert>
#include <iostream>
#include <list>
#include <vector>
using std::vector;
using std::list;
using std::cout;
using std::endl;
void cartesian_product( list< vector<int> > sets, list< vector<int> > &product);
int main( int argc, char *argv[] ) {
list< vector<int> > sets = {
{1, 7, 5, 2},
{4, 2, 1},
{1, 9, 4, 6, 4, 1, 2},
{9, 4}
};
list< vector<int> > product;
cartesian_product( sets, product );
for ( auto& x : product ) {
cout << "{ ";
for ( auto k : x ) {
cout << k << " ";
}
cout << "}" << endl;
}
}