C++ 使用STL列出特定子集

C++ 使用STL列出特定子集,c++,stl,combinations,C++,Stl,Combinations,假设我有一个数字范围,比如{2,3,4,5},以这个顺序存储在std::vector v中,我想列出所有可能的子集,它们使用STL以5结尾。。。即: 2 3 4 5 2 3 5 2 4 5 3 4 5 2 5 3 5 4 5 5 (我希望我没有忘记任何:) 我尝试使用while(下一个置换(v.begin(),v.end()),但没有得到想要的结果:) 有人有主意吗 PS:那些做过google code jam 2010存档的人可能会认识到:)因为你可以使用我会使用std::set的任何容器,

假设我有一个数字范围,比如{2,3,4,5},以这个顺序存储在
std::vector v
中,我想列出所有可能的子集,它们使用STL以5结尾。。。即:

2 3 4 5
2 3 5
2 4 5
3 4 5
2 5
3 5
4 5
5
(我希望我没有忘记任何:)

我尝试使用
while(下一个置换(v.begin(),v.end())
,但没有得到想要的结果:)

有人有主意吗


PS:那些做过google code jam 2010存档的人可能会认识到:)

因为你可以使用我会使用std::set的任何容器,因为它就在我们想要表示的容器旁边。 现在,您的任务是找到以5结尾的所有子集,因此我们取初始集并从中删除5。 现在,我们希望得到这个新集合的所有子集,并在其末尾附加5

void subsets(std::set<std::set<int>> &sets, std::set<int> initial)
{
    if(initial.empty())
        return;

    sets.insert(initial);//save the current set in the set of sets

    std::set<int>::iterator i = initial.begin();
    for(; i != initial.end(); i++)//for each item in the set
    {
        std::set<int> new_set(initial);//copy the set
        new_set.erase(new_set.find(*i));//remove the current item
        subsets(sets, new_set);//recursion ...
    }
}
void子集(std::set&set,std::set initial)
{
if(initial.empty())
回来
set.insert(initial);//将当前集合保存在集合集合中
std::set::iterator i=initial.begin();
for(;i!=initial.end();i++)//集合中的每个项
{
std::set new_set(初始);//复制集合
new_set.erase(new_set.find(*i));//删除当前项
子集(集合,新集合);//递归。。。
}
}
集合
是一个包含所有所需子集的集合。
initial
是要包含其子集的集合。 最后用
子集调用它(所有子集,初始列表,不带5)

这将创建子集,最后您可以向所有子集追加5。顺便说一句,不要忘记空集:)


还要注意的是,创建和删除所有这些集合的效率不是很高。如果你想更快,最终的集合应该得到集合的指针,新的集合应该被动态分配…

使用排列来创建一个向量向量。然后使用函数将其排序为以5结尾的向量和不以5结尾的向量。

让我们重点讨论打印所有子集的问题。如你所知,如果你有
n
元素的向量,你将有
2^n
可能的子集。如果有
n
位整数,则最大存储值为
2^n
,这不是巧合。如果把每个整数看作是一个比特向量,那么迭代所有可能的值将给出所有可能的比特子集。好吧,我们通过迭代整数免费得到子集

假设vector包含不超过32个元素(超过40亿个可能的子集!),这段代码将打印vector
v
的所有子集(不包括空子集):

for(uint32\u t mask=1;mask<(1=1),+it)
{      

如果(m&1)std::couttomasz描述了一种解决方案,只要
n取出5,在剩余的集合中运行下一个置换,但只需将5添加回每个置换的末尾……这至少是我的天真方法。您是否可以编写自己的递归函数来实现这一点?或者您必须使用STL函数?我知道什么t subset的意思是,但我不知道你想要什么。为什么不把这个问题联系起来?@Bob:置换不会给你子集。这应该在适当的地方完成,还是你可以创建所有需要的额外集合?你是否必须使用std::vector还是std::set是允许的?我不认为他认为经典的std::set是唯一元素的集合,而是一个数学matical subset作为从容器中拾取元素的一种方式。实际上,对于2^32子集,它会生成TB的数据来打印它们。因此,对于这个问题,内置32位或64位整数更合适。显然,它根本无法解决原始的代码阻塞解决方案:)
for (uint32_t mask =1; mask < (1<<v.size()); ++mask)
{
  std::vector<int>::const_iterator it = v.begin();
  for (uint32_t m =mask; m; (m>>=1), ++it)
  {      
    if (m&1) std::cout << *it << " ";
  }
  std::cout << std::endl;
}