排列与组合生成类

// Copyright (c)
// All rights reserved.
//
//Describe : Premutation And Combination generater
//Author   : Qing
//Date     : 2015-01-19

#ifndef __PREMUTATION_COMBINATION_H__
#define __PREMUTATION_COMBINATION_H__

#include <bitset>
#include <vector>
#include <algorithm>

namespace Qing
{
    template<typename T, unsigned int ElementCount>
    class PermutationCombination
    {
    public:

        PermutationCombination(void) {}
        ~PermutationCombination(void){}

        bool GetCombination(const std::vector<T> &SourceVector, int CombinationElementCount, std::vector<std::vector<T> > &ResultVector);
        bool GetPermutation(const std::vector<T> &SourceVector, int PermutationElementCount, std::vector<std::vector<T> > &ResultVector);

    private:

        bool AdjustPosition(std::bitset<ElementCount> &FlagArray, unsigned int SourceVectorElementCount);
    };

    template<typename T, unsigned int ElementCount>
    bool PermutationCombination<T,ElementCount>::GetCombination(const std::vector<T> &SourceVector, int CombinationElementCount, std::vector<std::vector<T> >& ResultVector)
    {
        if(SourceVector.size() <= 0 || CombinationElementCount <= 0 || CombinationElementCount > static_cast<int>(SourceVector.size()))
        {
            return false;
        }

        std::bitset<ElementCount> FlagArray;
        for(int Index = 0; Index < CombinationElementCount; Index++)
        {
            FlagArray.set(Index);
        }

        do
        {
            ResultVector.push_back(std::vector<T>(CombinationElementCount, T()));
            std::vector<T> &TempArray = ResultVector[ResultVector.size()-1];

            std::vector<T>::size_type TempIndex = 0;
            for(std::size_t BitSetIndex = 0; BitSetIndex < FlagArray.size(); BitSetIndex++)
            {
                if(FlagArray[BitSetIndex])
                {
                    TempArray[TempIndex] = SourceVector[BitSetIndex];
                    if(++TempIndex == CombinationElementCount)
                    {
                        break;
                    }
                }
            }
        }
        while(AdjustPosition(FlagArray, SourceVector.size()));

        return true;
    }

    template<typename T, unsigned int ElementCount>
    bool PermutationCombination<T,ElementCount>::GetPermutation(const std::vector<T> &SourceVector, int PermutationElementCount, std::vector<std::vector<T> >& ResultVector)
    {
        if(SourceVector.size() <= 0 || PermutationElementCount <= 0 || PermutationElementCount > static_cast<int>(SourceVector.size()))
        {
            return false;
        }

        std::bitset<ElementCount> FlagArray;
        for(int Index = 0; Index < PermutationElementCount; Index++)
        {
            FlagArray.set(Index);
        }

        std::vector<T> TempArray(PermutationElementCount,T());

        do
        {
            std::vector<T>::size_type TempIndex = 0;
            for(std::size_t BitSetIndex = 0; BitSetIndex < FlagArray.size(); BitSetIndex++)
            {
                if(FlagArray[BitSetIndex])
                {
                    TempArray[TempIndex] = SourceVector[BitSetIndex];
                    if(++TempIndex == PermutationElementCount)
                    {
                        do
                        {
                            ResultVector.push_back(TempArray);
                        }
                        while (next_permutation(TempArray.begin(), TempArray.end()));

                        break;
                    }
                }
            }
        }
        while(AdjustPosition(FlagArray, SourceVector.size()));

        return true;
    }

    //*********************** 0-1 exchange algorithm ************************
    //  example : C(5,3)
    //      1   1   1   0   0
    //      1   1   0   1   0
    //      1   0   1   1   0
    //      0   1   1   1   0
    //      1   1   0   0   1
    //      1   0   1   0   1
    //      0   1   1   0   1
    //      1   0   0   1   1
    //      0   1   0   1   1
    //      0   0   1   1   1
    //*********************** 0-1 exchange algorithm ************************
    template<typename T, unsigned int ElementCount>
    bool PermutationCombination<T,ElementCount>::AdjustPosition(std::bitset<ElementCount> &FlagArray, unsigned int SourceVectorElementCount)
    {
        SourceVectorElementCount -= 1;
        for(unsigned int i = 0; i < SourceVectorElementCount; i++)
        {
            if(FlagArray[i] && !FlagArray[i+1])
            {
                FlagArray.reset(i);
                FlagArray.set(i + 1);

                if(!FlagArray[0] && i != 0)
                {
                    int TrueCount = 0;
                    for(unsigned int j = 0; j < i; j++)
                    {
                        if(FlagArray[j])
                        {
                            ++TrueCount;
                        }

                        FlagArray.reset(j);
                    }

                    for(int k = 0; k < TrueCount; k++)
                    {
                        FlagArray.set(k);
                    }
                }

                return true;
            }
        }

        return false;
    }
}

#endif
时间: 2024-10-14 00:43:34

排列与组合生成类的相关文章

排列组合生成算法

r排列生成: gen 递归层数d表示正在生成第d个元素. vis记录是否出现过. #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int n, r; int A[50], vis[50];//记录第i个元素是否生成过 int cnt; int rer; void output(int r) { for(int i = 0; i < r; i++) printf(

排列与组合

话说,初一的时候看到这样一道题:有一种彩票中奖率为1%,买一百张是不是一定能中奖?答案自然是否定的,但我在想,如果有200张彩票,两张有奖,买一百张中奖率是多少?一天晚上睡觉的时候真的忽然想出来了(那时还没有学排列组合,自己想出了组合公式),最后算出来大约是75%.(相信学过OI的同学就不用看本文了)    先解决这个问题:两百张彩票,买一百张有多少种排列方式?当年我就是在脑海里构造了一个类搜索树的东西(好吧,二维的线性搜索树……),简单地说我们买第一张彩票的时候有200种方案可选,买第二张时由

从排列到组合——深度优先搜索

前段时间在洛谷3.0上刷到一个题,让本人挠头了一段时间,RT: 题目描述 已知 n 个整数 x1,x2,-,xn,以及一个整数 k(k<n).从 n 个整数中任选 k 个整数相加,可分别得到一系列的和.例如当 n=4,k=3,4 个整数分别为 3,7,12,19 时,可得全部的组合与它们的和为: 3+7+12=22  3+7+19=29  7+12+19=38  3+12+19=34. 现在,要求你计算出和为素数共有多少种. 例如上例,只有一种的和为素数:3+7+19=29. 首先解决这个问题显

基于字典序的组合生成算法

基于字典序的组合生成算法 2010-12-02 01:22:52|  分类: 离散数学 |  标签:离散数学  排列组合   |举报 |字号大中小 订阅 一. 问题描述 给定非空集合A,按字典序的方法生成集合A的所有组合.关于字典序的概念,这里不做严格定义,只是做一简单解释. 字典序是字符串比较的一种方法.例如两个字符串 abcd,abef,这两个字符串谁大? 显然,abef>abcd:如何得出这个结论的呢? 从左至右依次比较每一个字符,首先比较两个串的第一个字符,都是a,相等:其次比较两个串的

排列和组合的求解

1)使用“分类计数原理”还是“分步计数原理”要根据我们完成某件事时采取的方式而定,可以分类来完成这件事时用“分类计数原理”,需要分步来完成这件事时就用“分步计数原理”:那么,怎样确定是分类,还是分步骤?“分类”表现为其中任何一类均可独立完成所给的事件,而“分步”必须把各步骤均完成才能完成所给事件,所以准确理解两个原理强调完成一件事情的几类办法互不干扰,相互独立,彼此间交集为空集,并集为全集,不论哪类办法都能将事情单独完成,分步计数原理强调各步骤缺一不可,需要依次完成所有步骤才能完成这件事,步与步

OI内的排列与组合(简单版)

§1基本原理 △让我们来看下面问题: 从甲地到乙地,可以乘火车,也可以乘汽车,还可以乘轮船.一天中,火车有4班,汽车有2班,轮船有3班.那么,一天中乘坐这些交通工具从甲地到乙地共有多少种不同走法?△分析:因为从甲地到乙地,乘火车有4种选择(方法),乘汽车有2种选择(方法),乘轮船有3种选择(方法).因此,一天中乘坐这些交通工具从甲地到乙地共有:4+2+3 = 9种不同的方法. ▲一般地,做一件事,完成它可以有n类方法,在第一类办法中有m1种不同的方法,在第二类办法中有m2种不同的方法,……,在第

C++实现根据类名动态生成类对象

在开发后台服务的过程中,我们常常需要从数据库中取数据,并将数据缓存在本地中,另外,我们的服务还需要有更新数据的能力:包括定时的主动更新以及数据库数据更新时服务收到通知的被动更新. 之前在需要用到以上功能的时候,模仿着组内通用的数据Cache部分的代码来写,十分方便,基本上只需要自己写两个类:一个是取数据并缓存数据的类XXXData,一个是扇出数据的类XXXFetcher. 在需要使用数据的时候,通过: FetcherFactory::getFetcher<XXXFetcher>() 即可获取一

构建施耐德楼控系统数据库后台服务器示例工程五(JAVA动态生成类)

在做数据库简易工具的过程中遇到了这么一个问题,即程序部署在tomcat下启动运行后,我们无法事先定义数据库中后续创建的表结构的Hibernate Bean对象,这样就需要我们在服务器运行起来后动态创建bean对象.cglib这个开源库即可解决我们的问题,动态创建JAVA对象. 1.cglib开源库简介 CGLIB(Code Generation Library)是一个开源项目,是一个强大的,高性能,高质量的Code生成类库,它可以在运行期扩展Java类与实现Java接口. 反编译后CGLIB结构

用Enterprise Architect从源码自动生成类图

http://blog.csdn.net/zhouyong0/article/details/8281192 /*references:感谢资源分享者.info:简单记录如何通过工具从源码生成类图,便于分析代码结构,对源码阅读挺有用.*/ 看点开源代码学习下,本想找个代码查看方便点的工具,便于理清代码层次,结果发现了Enterprise Architect这一好工具,试用下来还挺方便的.功能上和Rational Rose大致是一类,用处很广,很多我都不懂,知道能画各种UML图,支持的源码语言类型