题目
https://www.patest.cn/contests/pat-a-practise/1079
题意:将零售商-经销商-供应商这条链抽象为一棵树;供应商作为根节点,出货物的价格为p,然后从根结点开始每往下走一层,该层的货物价格将会在父亲结点的价格上增加r%,给出每个叶结点(即零售商)的货物量,求他们的价格之和。
解题思路
供应商-经销商-零售商三者的关系可以看作是树的根节点-内部节点-叶子结点的关系。因此问题就转化成求每个叶子结点的层号,然后乘以相应系数,累加即可。
一次BFS/DFS解决,DFS代码比较简洁。
AC代码
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <queue>
#include <cmath>
using namespace std;
const int maxn = 100005;
vector<int> follow[maxn]; //记录节点i的后续节点
int level[maxn]; //节点的层次
int visited[maxn] = {false};
double sale[maxn] = {0}; //零售商的编号集合
vector<int> retail; //零售商i的卖出数量
void BFS(int s)
{
queue<int> q;
q.push(s);
visited[s] = true;
level[s] = 0; //根节点层号为0
int out, son;
while (!q.empty())
{
out = q.front(); q.pop();
for (int i = 0; i < follow[out].size(); ++i)
{
son = follow[out][i];
if (!visited[son]) //保证子节点没访问过
{
level[son] = level[out] + 1; //子节点层次为父节点层次+1
visited[son] = true;
q.push(son);
}
}
}
}
void DFS(int index, int depth)
{
if (follow[index].size() == 0) //到达叶子结点
{
level[index] = depth; //也可以直接在这里累加到ans
return;
}
for (int i = 0; i < follow[index].size(); ++i) //对每个子节点搜索
DFS(follow[index][i], depth+1);
}
int main()
{
int n;
double p, r;
int cnt, tmp;
cin >> n >> p >> r;
for (int i = 0; i < n; ++i) //处理每个编号为i的节点
{
cin >> cnt;
if (cnt == 0) //叶子结点
{
cin >> sale[i];
retail.push_back(i); //零售商的编号集合
continue;
}
for (int j = 0; j < cnt; ++j)
{
cin >> tmp;
follow[i].push_back(tmp);
}
}
BFS(0); //BFS
//DFS(0, 0); //DFS
double ans = 0;
for (int i = 0; i < retail.size(); ++i) //累加零售商的售价
{
tmp = retail[i];
ans += sale[tmp] * p * pow(1.0+r/100, level[tmp]);
}
printf("%.1f\n", ans);
return 0;
}