原题链接:
https://pintia.cn/problem-sets/994805342720868352/exam/problems/type/7?problemSetProblemId=994805424153280512&page=0
注意点:
- 剪枝:DFS函数中引入了tempSum这个参数进行剪枝,当tempSum大于或等于目标权重和时return,减少遍历的次数。
- 不同路径的排序:这里使用二维向量+自定义排序函数完成题目所需。
- 权重之和为根节点到叶节点,所以需要在将路径存入对应向量时进行判断。
代码:
#include <iostream>
#include <vector>
#include <algorithm>
#include <math.h>
using namespace std;
#define endl '\n'
struct node {
int weight;
vector<int> children;//存储该节点的孩子节点编号
};
node n[100];//n[0]代表编号为00的根节点
int N;//树的节点数
int M;//非叶节点数
int S;//要求的权重总和
int sum[100];//记录从根到这个节点的权重总和,实现记忆化搜索,减少遍历次数
vector<vector<int> > ans;//二维向量。存储结果
vector<int> tempAns;//存储已经走过的节点权重
void DFS(int x,int tempSum) {//x表示遍历到哪个节点的编号了,tempSum表示已经走过的权重总和
if (tempSum > S) {
return;
}
else if (tempSum == S) {
if (n[x].children.size() == 0) {
ans.push_back(tempAns);
}
return;
}
for (int i = 0; i < n[x].children.size(); i++) {
int child = n[x].children[i];
tempAns.push_back(n[child].weight);
DFS(child, tempSum + n[child].weight);
tempAns.pop_back();
}
return;
}
bool cmp(vector<int>& a, vector<int>& b) {
for (int i = 0; i < min(a.size(), b.size()); i++) {
if(a[i]!=b[i]){
return a[i] > b[i];
}
}
return false;//相同,任意返回一个bool值
}
signed main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
//input
cin >> N >> M >> S;
for (int i = 0; i < N; i++) {
cin>>n[i].weight;
sum[i] = n[i].weight;
}
for (int i = 0; i < M; i++) {
int ID, K;
cin >> ID >> K;
for (int j = 0; j < K; j++) {
int tempChild;
cin >> tempChild;
n[ID].children.emplace_back(tempChild);
}
}
tempAns.emplace_back(n[0].weight);
DFS(0,n[0].weight);
//cout << "pause" << endl;
sort(ans.begin(), ans.end(), cmp);
for (int i = 0; i < ans.size(); i++) {
for (int j = 0; j < ans[i].size(); j++) {
cout << ans[i][j];
if (j + 1 == ans[i].size()) {
cout << endl;
}
else {
cout << " ";
}
}
}
return 0;
}