这几道题都是一般树的遍历(DFS知识点)所以放在一起水过了;但遗憾的是我的 A1079 和 A1090 都是 PA,不过还是先记录下思路,刷完全部知识点再回头来看下细节
我对于一般树遍历的知识点主要关注 3 个地方,这 3 个地方找出来基本就能解:
//1. 结构体定义 //2. 输入 //3. dfs() 定义
最关键的是第三点:dfs() 定义,其实就是一般树的遍历。思路如下:
/* 伪码 */ void dfs(树结构结点, 其他条件) { /* 死胡同 */ if (一般都是无孩子) {...} /* 岔道口 */ for (遍历当前结点的所有孩子) dfs(); }
具体到怎么解题:
回到题目中,首先 A1079 大致题意是算所有叶子的权值,不过这个权值的计算稍微有点不同(和当前结点的深度也有关)。像这种 DFS() 遍历过程中需要额外完成的操作都可以套在模板 DFS() 参数 "其他条件" 中,并且因为要记录权值,所以树结点的结构体也要一个相应的成员变量来保存这些信息,所以第一点 "结构体定义" ,起来长这样:
struct node_t { double weight; vector<int> child; };
接下来考虑这棵树怎么组织,也就是第二点 "输入",其实也是像 A1053 那样组织成二维数组比较合适(A1053 也是考察一般树遍历的知识点)
第三点 "dfs() 定义",套模板修改即可:
/* 伪码 */ void dfs(node_t* t, double w) {//树结构结点 t,其他条件(这里是权值累加和) w node_t* cur = t; /* 死胡同 */ if (cur->child.size()) cur->weight = w * (1 + r);//非叶结点:将累加权值保存到其成员变量上 else sales += w * (1 + r) * cur->weight;//叶结点:直接将累加权值累加到总和 /* 岔道口 */ for (unsigned i = 0; i < cur->child.size(); ++i) dfs(&tree[cur->child[i]], cur->weight); }
其他两题也是同样道理