【题解 | DFS】天梯赛练习集:功夫传人

功夫传人

一门武功能否传承久远并被发扬光大,是要看缘分的。一般来说,师傅传授给徒弟的武功总要打个折扣,于是越往后传,弟子们的功夫就越弱…… 直到某一支的某一代突然出现一个天分特别高的弟子(或者是吃到了灵丹、挖到了特别的秘笈),会将功夫的威力一下子放大 N N N 倍 —— 我们称这种弟子为“得道者”。

这里我们来考察某一位祖师爷门下的徒子徒孙家谱:假设家谱中的每个人只有 1 1 1 位师傅(除了祖师爷没有师傅);每位师傅可以带很多徒弟;并且假设辈分严格有序,即祖师爷这门武功的每个第i代传人只能在第 i − 1 i-1 i1 代传人中拜 1 1 1 个师傅。我们假设已知祖师爷的功力值为 Z Z Z ,每向下传承一代,就会减弱 r % r\% r% ,除非某一代弟子得道。现给出师门谱系关系,要求你算出所有得道者的功力总值。

输入格式:

输入在第一行给出3个正整数,分别是: N ( ≤ 1 0 5 ) N(≤10^5 ) N105 ——整个师门的总人数(于是每个人从0到N−1编号,祖师爷的编号为0);Z——祖师爷的功力值(不一定是整数,但起码是正数);r ——每传一代功夫所打的折扣百分比值(不超过100的正数)。接下来有N行,第i行(i=0,⋯,N−1)描述编号为i的人所传的徒弟,格式为:

K i , I D [ 1 ] , I D [ 2 ] , ⋯ , I D [ K i ] K_i,ID[1],ID[2], ⋯ ,ID[K_i] KiID[1]ID[2]ID[Ki],其中 K i K_i Ki 是徒弟的个数,后面跟的是各位徒弟的编号,数字间以空格间隔。 K i K_i Ki为零表示这是一位得道者,这时后面跟的一个数字表示其武功被放大的倍数。

输出格式:

在一行中输出所有得道者的功力总值,只保留其整数部分。题目保证输入和正确的输出都不超过 1 0 10 10^{10} 1010

输入样例:

10 18.0 1.00
3 2 3 5
1 9
1 4
1 7
0 7
2 6 1
1 8
0 9
0 4
0 3

输出样例:

404

解题思路:

首先,建立一棵树,然后使用深度优先搜索(DFS)来遍历这棵树。在DFS的过程中,如果遇到的人是得道者,就更新他的功力值。如果遇到的人不是得道者,就遍历他的所有徒弟,递归地调用DFS函数,更新他的徒弟的功力值。最后遍历所有的人,找到所有的得道者,计算他们的功力值的总和。

#include <iostream>
#include <vector>
using namespace std;

struct Person {
    vector<int> disciples;  // 徒弟
    double power;  // 功力值
};

vector<Person> persons;  // 存储所有的人
double Z, r;  // Z是祖师爷的功力值,r是功力值的衰减率

// 遍历并更新每个人的功力值
void dfs(int index, double power) {
    if (persons[index].disciples.empty()) {  // 如果这个人是得道者
        persons[index].power *= power;  // 更新他的功力值
    } else {  // 如果这个人不是得道者
        for (int disciple : persons[index].disciples) {  // 遍历他的所有徒弟
            dfs(disciple, power * (1 - r));  // 更新他的徒弟的功力值
        }
    }
}

int main() {
    int N;  // N个人
    cin >> N >> Z >> r;
    r /= 100;  // 将r转换为百分比
    persons.resize(N); 
    for (int i = 0; i < N; i++) {  // 读取每个人的信息
        int K;  // K是这个人的徒弟的数量
        cin >> K;
        if (K == 0) {  // 如果这个人是得道者
            cin >> persons[i].power;  // 读取他的功力值
        } else {  // 如果这个人不是得道者
            persons[i].disciples.resize(K);
            for (int j = 0; j < K; j++) {  // 读取他的所有徒弟
                cin >> persons[i].disciples[j];
            }
        }
    }
    dfs(0, Z);  // 从祖师爷开始遍历这棵树,并更新每个人的功力值
    double totalPower = 0;  // 存储所有得道者的功力值的总和
    for (Person& person : persons) {  // 遍历所有的人
        if (!person.disciples.empty()) continue;  // 如果这个人不是得道者,就跳过他
        totalPower += person.power;  // 如果这个人是得道者,就将他的功力值加到总和中
    }
    cout << (int)totalPower << endl;
    return 0;
}

测试链接:L2-020 功夫传人

相关推荐

  1. 题解 | DFS天梯练习功夫传人

    2024-04-20 12:56:02       40 阅读
  2. 团队程序天梯练习题题解

    2024-04-20 12:56:02       38 阅读
  3. pta团体程序设计天梯——练习(1-10题)

    2024-04-20 12:56:02       53 阅读
  4. 洛谷的练习天梯

    2024-04-20 12:56:02       36 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-20 12:56:02       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-20 12:56:02       106 阅读
  3. 在Django里面运行非项目文件

    2024-04-20 12:56:02       87 阅读
  4. Python语言-面向对象

    2024-04-20 12:56:02       96 阅读

热门阅读

  1. Rust开发笔记 | 所有权系统及其对内存管理的影响

    2024-04-20 12:56:02       38 阅读
  2. ClickHouse 集群部署(不需要 Zookeeper)

    2024-04-20 12:56:02       32 阅读
  3. OPTEE RUST支持&构建并运行支持RUST的CA和TA

    2024-04-20 12:56:02       37 阅读
  4. C++指针

    C++指针

    2024-04-20 12:56:02      35 阅读
  5. mongodb 安装

    2024-04-20 12:56:02       36 阅读
  6. 骑砍2霸主MOD开发(5)-游戏事件

    2024-04-20 12:56:02       37 阅读