首先捋一下题,给了一个初始值,然后没传一代就减少一点,如果是得到者就让他获得的功力乘以倍数,最后求得到者功力总和。那么也就是说我们需要找两个东西:1.得到者 2.得到者是第几代。
思路一:建立一个二维动态数组,然后在输入的时候横坐标代表这个人的编号,这一行就存储它的徒弟的编号。如果是得到者的话就只存储它的倍数,顺便建立一个标记数组将对应编号标记为1(原先为0).这样接收完数据后。之间开始DFS,只要该行下标不是被标记的行就挨着搜索就行。代码如下:
#include<bits/stdc++.h>
using namespace std;
int n,k,x,vis[100010];
double sum,z,r;
vector<vector<int>>v;
void dfs(int index,double power)
{
if(vis[index])
{
sum+=power*v[index][0];
return ;
}
for(int i=0;i<v[index].size();i++)
dfs(v[index][i],power*(1-r/100));
}
int main()
{
cin>>n>>z>>r;
v.resize(n);
for(int i=0;i<n;i++)
{
cin>>k;
if(!k)
{
cin>>x;
vis[i]=1;
v[i].push_back(x);
}
while(k--)
{
cin>>x;
v[i].push_back(x);
}
}
dfs(0,z);
cout<<(int)sum;
}
思路二:相对于思路一,我个人更偏向于这种解法,虽然技术含量不高,但是易于理解。精髓就在于接收数据将得到者的下标和倍数存到一个队列中(数组也可以,个人习惯)。然后不是得到者的用一个pre数组来存储它的前驱结点(就是它的师父)。这样接收完数组后,只有pre[i]==i的点是祖先。然后我们开始遍历队列,
每次取队头,然后根据pre数组找他是第几代,最后就可以算出来这个得到者获得了多少功力,代码如下:
#include<bits/stdc++.h>
using namespace std;
struct node
{
int p,index;
};
int n,k,x,pre[100010],root;
queue<node>q;
double z,r,sum;
double deal()
{
while(!q.empty())
{
node u=q.front();
q.pop();
int cnt=0,a=u.index;
while(pre[a]!=a)
{
a=pre[a];
cnt++;
}
sum+=z*pow(1-r/100,cnt)*u.p;
}
return sum;
}
int main()
{
cin>>n>>z>>r;
for(int i=0;i<n;i++) pre[i]=i;
for(int i=0;i<n;i++)
{
cin>>k;
if(!k)
{
cin>>x;
q.push({x,i});
}
while(k--)
{
cin>>x;
pre[x]=i;
}
}
cout<<deal();
}