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