【机试练习】【C++】【PAT A1053】Path of Equal Weight

24 篇文章 0 订阅

同样思路使用两种不同的编码实现。

#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;

struct Node{
	int weight;
	vector<int> child;
};
Node t[1010];
vector<vector<int> > serialStore;
vector<int> tmpSerial;
bool cmp(vector<int> a, vector<int> b){
	if(a.empty() || b.empty()){
		return a.empty();
	}
	int minL = min(a.size(), b.size());
	for(int i = 0; i < minL; i++){
		if(a[i] != b[i]) return a[i] > b[i]; // 关键在这里的大于号 
	}
	return false;
} 

// 测试cmp是否工作的函数
void sortSerial(){
	vector<int> tmp;
	tmp.push_back(10);tmp.push_back(3);tmp.push_back(3);tmp.push_back(6);tmp.push_back(2);
	serialStore.push_back(tmp);
	tmp.clear();
	tmp.push_back(10);tmp.push_back(5);tmp.push_back(2);tmp.push_back(7);
	serialStore.push_back(tmp);
	tmp.clear();
	tmp.push_back(10);tmp.push_back(4);tmp.push_back(10);
	serialStore.push_back(tmp);
	tmp.clear();
	tmp.push_back(10);tmp.push_back(3);tmp.push_back(3);tmp.push_back(6);tmp.push_back(2);
	serialStore.push_back(tmp);
	tmp.clear();
	sort(serialStore.begin(), serialStore.begin() + 4, cmp);
	while(!serialStore.empty()){
		vector<int> v = serialStore.front();
		while(!v.empty()){
			printf("%d ", v.front());
			v.erase(v.begin(), v.begin() + 1);
		} 
		serialStore.erase(serialStore.begin(), serialStore.begin() + 1);
		printf("\n");
	}
}



int N, M, S;
// N: 节点个数, M: 非叶节点个数, S: 给定权值


void printLayer(int num){
	printf("%02d", num); // 不足两位,以0补齐 
}



void preOrder(int root){
//	printLayer(root);
//	printf(" %d %d\n", t[root].weight, nowLayer);
	// 访问节点的逻辑应该就是:将节点的权值加入临时序列存储
	tmpSerial.push_back(t[root].weight); 
	if(!t[root].child.empty()){
		for(int i = 0; i < t[root].child.size(); i++){
			preOrder(t[root].child[i]);		
		}
	} else{ // 叶子节点的逻辑 
		// 到达叶子节点之后 先计算加和
		int sum = 0;
		for(int i = 0; i < tmpSerial.size(); i++){
			sum += tmpSerial[i];
		} 
		if(sum == S){
			serialStore.push_back(tmpSerial);	
		}
	}
	tmpSerial.pop_back(); 
}


int main(){
	scanf("%d %d %d", &N, &M, &S);
	for(int i = 0; i < N; i++){
		scanf("%d", &(t[i].weight));
	}
	int nodeIdx, childNum;
	int tmpWeight;
	while(scanf("%d %d", &nodeIdx, &childNum) != EOF){
		while(childNum --){
			scanf("%d", &tmpWeight);
			t[nodeIdx].child.push_back(tmpWeight);
		}
	}
	// 尝试先根遍历整棵树 
	preOrder(0);
//	sortSerial();	
	if(serialStore.size() > 1)
		sort(serialStore.begin(), serialStore.begin() + serialStore.size(), cmp);
	while(!serialStore.empty()){
		vector<int> v = serialStore.front();
		while(!v.empty()){
			printf("%d", v.front());
			v.erase(v.begin());
			if(!v.empty())
				printf(" ");
		} 
		serialStore.erase(serialStore.begin());
		if(!serialStore.empty())
			printf("\n");
	}
	return 0; 
}

另一种方法


#include<cstdio>
#include<vector> 
#include<queue>
#include<algorithm>
using namespace std;

// 建立树的节点
struct node{
	int weight = -1;
	vector<int> child;
}tree[110]; // 节点最大个数 

int N = -1, M = -1, S = -1;

vector<vector<int> > solve; // 结果集合是一个二维数组 
vector<int> now_trace;


bool cmp(vector<int> a, vector<int> b){
	int len = min(a.size(), b.size());
	// 先遍历都有的
	for(int i = 0; i < len; i++){
		if(a[i] != b[i]){
			return a[i] > b[i];
		}
	} 
	// 如果循环完了还不return 那谁长谁大
	return a.size() > b.size();
}



// sum 是上层传上来的 
void DFS(int idx, int sum){
	// 访问根节点
	int this_weight = tree[idx].weight;
	sum += this_weight;
	now_trace.push_back(this_weight);
	if(sum < S){
		// 循环遍历子节点
		for(int i = 0; i < tree[idx].child.size(); i++){
			DFS(tree[idx].child[i], sum);
		} 
	} else if(sum == S){
		if(tree[idx].child.empty()) {// 如果是叶子节点则符合要求
			solve.push_back(now_trace);
		}
	}
	now_trace.pop_back();
}


int main(){
	// 扫描节点个数,叶子节点个数 ,给定权值 
	scanf("%d %d %d", &N, &M, &S);
	// 扫描权值数组 
	for(int i = 0; i < N; i ++){
		scanf("%d", &(tree[i].weight));
	}
	// 扫描每个节点 
	// 新建节点不使用p306 newNode 因为这里很多东西都是给定好的
	for(int i = 0; i < M; i ++){ // 直接遍历非叶节点 
		int idx = -1;
		scanf("%d", &idx);
		int child_num = -1;
		scanf("%d", &child_num);
		while(child_num --){
			int child_idx = -1;
			scanf("%d", &child_idx);
			tree[idx].child.push_back(child_idx);
		}
	}
	// 测试一下结构 
//	for(int i = 0; i < N; i++){
//		printf("%0d %0d ", i, tree[i].child.size());
//		for(int j = 0; j < tree[i].child.size(); j++){
//			printf("%d ", tree[i].child[j]);
//		}
//		printf("\n");
//	}
	// 测试一下层序遍历
//	queue<int> q;
//	q.push(0);
//	while(!q.empty()){
//		int front = q.front();
//		q.pop();
//		printf("%d ", tree[front].weight);
//		for(int i = 0; i < tree[front].child.size(); i++){
//			q.push(tree[front].child[i]);
//		}
//	}
	// 成功扫描进来了,之后就是按要求进行先根遍历并记录序列
	DFS(0, 0);
	// 测试之后能成功遍历 下面面临排序 
	sort(solve.begin(), solve.end(), cmp);
	for(int i = 0; i < solve.size(); i++){
		for(int j = 0; j < solve[i].size(); j++ ){
			printf("%d", solve[i][j]);
			if(j != solve[i].size() - 1){
				printf(" ");
			}
		}
		if(i != solve.size() - 1){
			printf("\n");
		}
	}	
	return 0;
}

附AC结果
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值