写出满足如下要求的C++代码:分支限界法解决子集和数的问题,输入格式: 第一行为一个不超过200的正整数n,表示总集规模; 第二行是正整数M,表示子集的和数; 第三行是总集中n个正整数,中间用空格隔开。 输出格式: 如果有答案,则输出所有满足条件的子集(用可变长度数组表示符合条件的一个子集,子集中元素表示被选中的数值的下标); 如果没有答案,则输出“no solution!”。
时间: 2024-03-19 20:43:11 浏览: 93
以下是满足要求的C++代码:
```cpp
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
const int MAXN = 200;
struct Node {
int sum; // 子集和
vector<int> path; // 子集
};
int n, m;
int a[MAXN + 5];
bool vis[MAXN + 5];
bool cmp(Node a, Node b) {
return a.sum < b.sum;
}
void dfs(int u, int sum, vector<int> path, vector<Node>& ans) {
if (sum > m) return; // 剪枝
if (u > n) {
if (sum == m) {
Node node = {sum, path};
ans.push_back(node); // 加入答案
}
return;
}
dfs(u + 1, sum, path, ans); // 不选当前数
path.push_back(u);
dfs(u + 1, sum + a[u], path, ans); // 选当前数
}
int main() {
cin >> n >> m;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
vector<int> path;
vector<Node> ans;
dfs(1, 0, path, ans);
if (ans.empty()) {
cout << "no solution!\n";
} else {
sort(ans.begin(), ans.end(), cmp);
for (int i = 0; i < ans.size(); i++) {
for (int j = 0; j < ans[i].path.size(); j++) {
cout << ans[i].path[j] << " ";
}
cout << "\n";
}
}
return 0;
}
```
解释一下代码的思路:
- 首先输入总集规模n和子集和数M,以及n个正整数a[i]。
- 然后定义一个节点结构体Node,包含子集和sum和子集path(用vector表示)。
- 定义一个dfs函数,其中u表示当前考虑到第几个数,sum表示当前子集的和,path表示当前子集的路径,ans表示答案集合。
- 在dfs函数中,先判断是否超过子集和,如果超过则剪枝;如果已经考虑完了所有数,判断当前子集和是否为M,如果是则将当前子集加入答案集合。
- 接着分别考虑选或不选当前数,进行递归搜索。
- 最后在主函数中调用dfs函数,如果答案集合为空,输出"no solution!";否则对答案集合进行排序,依次输出每个子集的路径。
阅读全文