码迷,mamicode.com
首页 > 其他好文 > 详细

枚举集合划分方案

时间:2015-03-15 23:00:59      阅读:203      评论:0      收藏:0      [点我收藏+]

标签:集合划分   枚举   

1. 题目
有n个互不相同的整数,将其划分成m个均不为空的集合,枚举所有的划分方案。
2. 分析
(1)该问题明显不同于整数划分问题(http://blog.csdn.net/woniu317/article/details/39250403 ),整数划分问题等价于划分有n个元素集合的方案总数,且集合中的元素相同,因为若不同即使个数相同划分方案也为不同。
(2) 易得该问题属于典型的回溯问题。
3. 实现

#include <vector>
#include <iostream>
using namespace std;

typedef vector<int> mySet;
#define N 5
#define M 4

vector<mySet> groups(M);
int data[N] = {1, 2, 3, 4, 5};

void ds(int i)
{
    if (i > N - 1)
    {
        for (int j = 0; j < M; ++j)
        {
            if (0 == groups[j].size())
            {
                //存在为空的组,因此不是结果
                return;
            }
        }
        //输出结果
        for (int j = 0; j < M; ++j)
        {
            cout << "set" << j << ": ";
            for (int k = 0; k < groups[j].size(); ++k)
            {
                cout << groups[j][k] << " ";
            }
        }
        cout << endl;
        return;
    }

    //  A.push_back(data[i]);
    //将第i个元素尝试放入第0个集合中
    groups[0].push_back(data[i]);
    ds(i + 1);
    for (int j = 1; j < M; ++j)
    {
        //若第j-1个集合元素个数多于一个则可以回溯,反之不可以
        if (groups[j - 1].size() > 1)
        {
            //将data[i]从第j-1个集合移除,尝试放入集合j
            groups[j - 1].erase(groups[j - 1].end() - 1);
            groups[j].push_back(data[i]);
            ds(i + 1);
            //运行至最后一个集合回溯时需撤销元素
            if (j == M - 1)
            {
                groups[j].erase(groups[j].end() - 1);
            }
        }
        else
        {
            groups[j - 1].erase(groups[j - 1].end() - 1);
            break;
        }
    }
}

int main()
{
    ds(0);
    return 0;
}

枚举集合划分方案

标签:集合划分   枚举   

原文地址:http://blog.csdn.net/woniu317/article/details/44282133

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!