pta l2-20(功夫传人)

题目链接:https://pintia.cn/problem-sets/994805046380707840/problems/994805059118809088

题意:给定n个人,编号0~n-1,0为祖先,每个人有一个师傅,每次从师傅传功夫到徒弟时,功力值会削弱r,但可能会出现得道者,功力翻n倍,计算所有得道者功力值之和。

思路:因为计算功力值时要从祖先开始逐渐向下计算,所以我们需要存储每个人的徒弟,然后从上向下遍历即可,我这里用的是邻接表实现的,定义maxn个表头结点head,head[i]其中包括它的第一个徒弟编号nxt,翻的倍数,功力值;定义maxn个表结点,指向其兄弟结点。然后用dfs从祖先编号0开始搜即可,但我被两个细节点卡了一个多小时,卡到崩溃QAQ:1.输入的r是[0,100]的值,还需除100; 2. 我写代码没带脑子,在dfs函数中用全局变量tmp作为指向徒弟的指针,然后程序一直在那运行错误的结果...

AC代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int maxn=100005;
 5 struct node{
 6     int nxt,bg;
 7     double gl;
 8 }head[maxn];
 9 
10 int n,k,tmp,nxt[maxn];
11 double z,r,sum;
12 
13 void dfs(int p){
14     if(head[p].bg)
15         sum+=head[p].gl*head[p].bg;
16     else{
17         int t=head[p].nxt;
18         while(t){
19             head[t].gl=head[p].gl*r;
20             dfs(t);
21             t=nxt[t];
22         }
23     }
24 }    
25 
26 int main(){
27     scanf("%d%lf%lf",&n,&z,&r);
28     r=1.0-0.01*r;
29     head[0].gl=z;
30     for(int i=0;i<n;++i){
31         scanf("%d",&k);
32         if(!k)
33             scanf("%d",&head[i].bg);
34         else
35             while(k--){
36                 scanf("%d",&tmp);
37                 nxt[tmp]=head[i].nxt;
38                 head[i].nxt=tmp;
39             }
40     }
41     dfs(0);
42     printf("%lld\n",(long long)sum);
43     return 0;
44 }

猜你喜欢

转载自www.cnblogs.com/FrankChen831X/p/10573996.html