zoukankan      html  css  js  c++  java
  • [经典算法] 排列组合-N元素集合的所有子集(二)

    题目说明:

    给定一组数字或符号,按照字典序产生所有可能的集合(包括空集合),例如给定1 2 3,则可能的集合为:{}、{1}、{1,2}、{1,2,3}、{1,3}、{2}、{2,3}、{3}。

    题目解析:

    如果要产生字典顺序,例如若有4个元素,则:

    {} => {1} => {1,2} => {1,2,3} => {1,2,3,4} =>
    {1,2,4} =>
    {1,3} => {1,3,4} =>
    {1,4} =>
    {2} => {2,3} => {2,3,4} =>
    {2,4} =>
    {3} => {3,4} =>
    {4}

    简单的说,如果有n个元素要产生可能的集合,当依序产生集合时,如果最后一个元素是n,而倒数第二个元素是m的话,

    例如:

    {a b c d e n}

    则下一个集合就是{a b c d e+1},再依序加入后续的元素。
    例如有四个元素,而当产生{1 2 3 4}集合时,则下一个集合就是{1 2 3+1},也就是{1 2 4},由于最后一个元素还是4,所以下一个集合就是{1 2+1},也就是{1 3},接下来再加入后续元素4,也就是{1 3 4},由于又遇到元素4,所以下一个集合是{1 3+1},也就是{1 4}。

    程序代码:

    #include <gtest/gtest.h>
    using namespace std;
    
    void ShowResult(int State[], int nSize)
    {
        cout << "{";
        for (int i=0; i<nSize; ++i)
        {
            cout << State[i] << " ";
        }
        cout << "}
    ";
    }
    
    // 产生字典序的子集
    int GenerateOrderSubset(int nSize)
    {
        if (nSize==0)
        {    
            cout << "{}" << endl;
            return 1;
        }
        
        int nCount = 0;
        int nPos = -1;
        int *State = new int[nSize];
        memset(State, 0, sizeof(int)*nSize);
    
        do
        {
            nCount++;
            ShowResult(State, nPos+1);
            if (nPos==-1)
            {
                State[++nPos] = 1;
                continue;
            }
    
            if (State[nPos] < nSize) // 递增集合个数
            {
                State[nPos+1] = State[nPos] + 1;
                nPos++;
            }        
            else if(nPos > 0) // 如果不是第一个位置
            {
                nPos;        // 倒退
                State[nPos]++;// 下一个集合尾数
            }
            else
            { 
                break;        // 已倒退至第一个位置
            }
        }
        while(true);
    
        delete[] State;
    
        return nCount;
    }
    
    TEST(Algo, tCombination)
    {    
        // 有字典序
    
        // 0个数子集合数 =〉2^0 = 1
        ASSERT_EQ(GenerateOrderSubset(0), 1);
    
        // 3个数子集合数 =〉2^3 = 8
        ASSERT_EQ(GenerateOrderSubset(3), 8);
    
        // 5个数子集合数 =〉2^5 = 32
        ASSERT_EQ(GenerateOrderSubset(5), 32);
    
        // 10个数子集合数 =〉2^10 = 1024
        ASSERT_EQ(GenerateOrderSubset(10), 1024);
    }

    参考引用:

    http://www.cnblogs.com/Quincy/p/4838051.html

    Book16  看书、学习、写代码
  • 相关阅读:
    [TJOI2007]小朋友
    弦图小结
    Bzoj2141: 排队
    [SYZOI Round1] 滑稽♂树
    Bzoj2244: [SDOI2011]拦截导弹
    Bzoj1492: [NOI2007]货币兑换Cash(不单调的斜率优化)
    Bzoj1495: [NOI2006]网络收费
    Bzoj1496: [NOI2006]千年虫
    Bzoj1498&1416: [NOI2006]神奇的口袋
    Bzoj4553: [Tjoi2016&Heoi2016]序列
  • 原文地址:https://www.cnblogs.com/Quincy/p/4838359.html
Copyright © 2011-2022 走看看