天梯赛L2-020 功夫传人
题目详情:
思路:
这个题目的看着就感觉需要深搜一下,不妨将样例画出来,思路就突然涌来了。很明显的一道深搜的题目:
题目刚开始输入的一行信息整体的信息:宗门人数,祖师爷功力,功力降低的百分数
就开始输入师徒的信息了:徒弟个数,徒弟编号,如果徒弟个数为0证明这货是个得道者,就是我们要找的人,后面就不是徒弟编号了,而是他功力要增加的倍数。
这里呢我画的图把他们隐藏的编号也写了出来,这个样子更容易让我们画出来我们需要的图。
很明显呢,看着这个图,就知道我们要遍历一棵树。那么肯定是要从头开始遍历的,这个题目不用我们找谁是根节点,题目要求了根节点就是0。直接遍历就好,那么就需要一个遍历的函数了:
我们可以先写一个大致意思的函数,要先考虑它的参数,几个参数呢:这个题目不妨设两个,一个编号,一个功力
void dfs(编号,功力)
{
if(他有标记)//我们把得道者标记一下
{
总功力 += 它的功力
}
else
{
dfs(它的徒弟,徒弟的功力)
}
}
具体的实现呢还得是看下文的程序。
详细代码:
//这个题目本质上就是遍历树。
//利用vector建立一个数组来存树,然后利用只有一个师傅的关系来递归
#include<bits/stdc++.h>
using namespace std;
const int maxn = 100000+5;
vector<int>Next[maxn];//存徒弟的编号
int n;
double z, r, sum=0;//记得sum要设置为全局变量,不然的话就得多传一个参数
double t[maxn]={0};//功力的倍数
void dfs(int id, double z)
{
if(t[id])//功力翻倍即得道者,可以作为得道者的标志
sum += z*t[id];
else
for(int i=0; i<Next[id].size(); i++)//递归求徒弟们的功力
{
dfs(Next[id][i], z*r);//让徒弟的编号进行递归
}
}
int main()
{
cin>>n>>z>>r;
r = (100-r)/100.0;//先变成百分数方便计算
int k, id;//徒弟个数,徒弟编号
for(int i=0; i<n; i++)
{
cin>>k;
if(k)
for(int j=0; j<k; j++)
{
cin>>id;
Next[i].push_back(id);
}
else
cin>>t[i];//如果功力的倍数不为0,那么就是得道者
}
dfs(0,z);//从祖师爷开始递归
cout<<(int)sum<<endl;//因为要求输出整数部分,直接强制类型转换
}
知识总结:
做这种图和树的深搜题,我的做法是先把图画出来,心中先出一个思路,可以更好的帮助我们解题。
这道题目没有遇到什么偏僻的知识,如果说你L2做到了这道题还没有掌握vector,set,map三种容器的基本使用,那你真的需要去补补这方面的知识。
另外我写题目喜欢用全局变量,一是全局变量有默认取值,二全局变量用起来真的方便,在每个函数中都可以使用,就不用在传参什么的了。