使用子集树和排列数两种方式求子集和问题,子集和问题就是集合中的多个数Xn求和等于指定数k,并使用c++语言给出相应代码以及注释,不要使用向量简洁明了给出思路以及树图
时间: 2024-01-22 16:19:20 浏览: 167
思路:
1. 子集树:
- 遍历所有可能的子集,计算子集和是否等于指定数k。
- 对于每个元素,都有两种选择:选择或不选择。
- 可以使用深度优先搜索(DFS)遍历整个子集树。
2. 排列数:
- 将原始集合拆分成两个部分:正数部分和负数部分。
- 计算正数部分的所有子集和、负数部分的所有子集和,并将它们分别存储在两个数组中。
- 对于每个正数子集和,查找负数子集和数组中是否存在一个值等于指定数k减去正数子集和。
- 如果存在,则说明原始集合中存在一组子集和等于指定数k。
树图:
```
{}
/ \
{} {4}
/ \ / \
{} {3} {4} {7}
/ \ / \ / \ / \
{} {2} {3} {5}{4} {7}{8}
```
代码实现:
1. 子集树
```c++
#include <iostream>
using namespace std;
const int N = 100;
int n, k, a[N];
bool st[N];
void dfs(int u, int sum) // u表示枚举到第几个元素,sum表示当前子集的和
{
if (u == n)
{
if (sum == k)
{
// 子集和等于k,做相应的处理
cout << "subsets found!" << endl;
}
return;
}
dfs(u + 1, sum); // 不选当前元素
dfs(u + 1, sum + a[u]); // 选择当前元素
}
int main()
{
cin >> n >> k;
for (int i = 0; i < n; i++) cin >> a[i];
dfs(0, 0);
return 0;
}
```
2. 排列数
```c++
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
const int N = 100;
int n, k, a[N];
vector<int> pos, neg; // 存储正数子集和和负数子集和
void dfs(int u, int sum, vector<int>& nums) // 枚举子集和
{
if (u == nums.size())
{
nums.push_back(sum); // 将当前子集和加入数组中
return;
}
dfs(u + 1, sum, nums); // 不选当前元素
dfs(u + 1, sum + nums[u], nums); // 选择当前元素
}
int main()
{
cin >> n >> k;
for (int i = 0; i < n; i++)
{
cin >> a[i];
if (a[i] >= 0) pos.push_back(a[i]);
else neg.push_back(-a[i]);
}
dfs(0, 0, pos); // 枚举正数子集和
dfs(0, 0, neg); // 枚举负数子集和
sort(neg.begin(), neg.end()); // 对负数子集和进行排序
for (int i = 0; i < pos.size(); i++)
{
int target = k - pos[i];
if (binary_search(neg.begin(), neg.end(), target))
{
// 子集和等于k,做相应的处理
cout << "subsets found!" << endl;
}
}
return 0;
}
```
阅读全文