【PAT甲级 - C++题解】1090 Highest Price in Supply Chain

简介: 【PAT甲级 - C++题解】1090 Highest Price in Supply Chain

1090 Highest Price in Supply Chain


A supply chain is a network of retailers(零售商), distributors(经销商), and suppliers(供应商)-- everyone involved in moving a product from supplier to customer.


Starting from one root supplier, everyone on the chain buys products from one’s supplier in a price P and sell or distribute them in a price that is r% higher than P. It is assumed that each member in the supply chain has exactly one supplier except the root supplier, and there is no supply cycle.


Now given a supply chain, you are supposed to tell the highest price we can expect from some retailers.

Input Specification:


Each input file contains one test case. For each case, The first line contains three positive numbers: N (≤105), the total number of the members in the supply chain (and hence they are numbered from 0 to N−1); P, the price given by the root supplier; and r, the percentage rate of price increment for each distributor or retailer. Then the next line contains N numbers, each number S**i is the index of the supplier for the i-th member. Sroot for the root supplier is defined to be −1. All the numbers in a line are separated by a space.

Output Specification:


For each test case, print in one line the highest price we can expect from some retailers, accurate up to 2 decimal places, and the number of retailers that sell at the highest price. There must be one space between the two numbers. It is guaranteed that the price will not exceed 1010.

Sample Input:

9 1.80 1.00
1 5 4 4 -1 4 5 3 6
• 1
• 2

Sample Output:

1.85 2


题意


供应链是由零售商,经销商和供应商构成的销售网络,每个人都参与将产品从供应商转移到客户的过程。


整个销售网络可以看作一个树形结构,从根部的供应商往下,每个人从上一级供应商中买入商品后,假定买入价格为 P ,则会以高出买入价 r% 的价格向下出售。


只有零售商(即叶节点)可以直接将产品销售给顾客。


现在,给定整个销售网络,输出零售商可达到的最高销售价格,保留两位小数,以及可达到最高销售价格的零售商的数量。


第一行包含三个数,N 表示供应链总成员数(所有成员编号从 0 到 N−1 ,根部供应商编号为 0 ),P 表示根部供应商的每件产品的售卖价格,r ,溢价百分比。


接下来一行输出 N 个数,分别表示 i 的上级供应商编号。


思路


我们可以用一个数组 p 来存储每个结点的父结点,并且再用一个数组 st 来判断每个结点是否是叶子结点。另外,给定上级结点编号是 -1 的结点是根结点。

通过树形 DP 来计算树的深度,用一个 f 数组来存储每次计算的值,这样就可以排除重复计算的步骤。

计算总销售额时只用判断每次遍历的结点是否为叶子结点即可,然后通过公式 P * pow(1 + R / 100, dfs(i)) 计算该叶子结点即零售商的销售额。其中,P 表示产品的单位价格,pow(1 + R / 100, dfs(i)) 则是计算 1 + R/100 的 dfs(i) 次方即每多一层关系次方数就加 1 。每次计算完之后,再去判断当前销售额是否是最大值,如果是最大值则更新答案,如果等于最大值则最大销售额的销售商数量加 1 。

输出最终结果,注意销售额最大值保留两个小数点。

代码

#include<bits/stdc++.h>
using namespace std;
const int N = 100010;
int n;
double P, R;
int p[N], f[N];
bool st[N];
//树形DP,记忆化搜索
int dfs(int u)
{
    //剪枝,如果f[u]已经被计算过,直接返回即可
    if (f[u] != -1)    return f[u];
    //如果该结点没有父结点,直接返回0,同时更新f[u]
    if (p[u] == -1)    return f[u] = 0;
    return f[u] = dfs(p[u]) + 1;
}
int main()
{
    cin >> n >> P >> R;
    //输入结点信息
    int root = 0;
    for (int i = 0; i < n; i++)
    {
        cin >> p[i];
        st[p[i]] = true;
        if (p[i] == -1)    root = i;
    }
    memset(f, -1, sizeof f);
    //找到零售商可达到的最高销售价格及该零售商的数量
    double res = 0;
    int cnt = 0;
    for (int i = 0; i < n; i++)
        if (!st[i])
        {
            double sum = P * pow(1 + R / 100, dfs(i));
            if (sum > res) res = sum, cnt = 1;
            else if (sum == res)   cnt++;
        }
    printf("%.2lf %d\n", res, cnt);
    return 0;
}
目录
相关文章
|
C++
【PAT甲级 - C++题解】1040 Longest Symmetric String
【PAT甲级 - C++题解】1040 Longest Symmetric String
68 0
|
算法 C++
【PAT甲级 - C++题解】1044 Shopping in Mars
【PAT甲级 - C++题解】1044 Shopping in Mars
88 0
|
C++
【PAT甲级 - C++题解】1117 Eddington Number
【PAT甲级 - C++题解】1117 Eddington Number
82 0
|
存储 C++ 容器
【PAT甲级 - C++题解】1057 Stack
【PAT甲级 - C++题解】1057 Stack
79 0
|
存储 C++
【PAT甲级 - C++题解】1055 The World‘s Richest
【PAT甲级 - C++题解】1055 The World‘s Richest
81 0
|
C++
【PAT甲级 - C++题解】1051 Pop Sequence
【PAT甲级 - C++题解】1051 Pop Sequence
85 0
|
29天前
|
存储 编译器 C语言
【c++丨STL】string类的使用
本文介绍了C++中`string`类的基本概念及其主要接口。`string`类在C++标准库中扮演着重要角色,它提供了比C语言中字符串处理函数更丰富、安全和便捷的功能。文章详细讲解了`string`类的构造函数、赋值运算符、容量管理接口、元素访问及遍历方法、字符串修改操作、字符串运算接口、常量成员和非成员函数等内容。通过实例演示了如何使用这些接口进行字符串的创建、修改、查找和比较等操作,帮助读者更好地理解和掌握`string`类的应用。
50 2
|
1月前
|
存储 编译器 C++
【c++】类和对象(下)(取地址运算符重载、深究构造函数、类型转换、static修饰成员、友元、内部类、匿名对象)
本文介绍了C++中类和对象的高级特性,包括取地址运算符重载、构造函数的初始化列表、类型转换、static修饰成员、友元、内部类及匿名对象等内容。文章详细解释了每个概念的使用方法和注意事项,帮助读者深入了解C++面向对象编程的核心机制。
103 5
|
1月前
|
存储 编译器 C++
【c++】类和对象(中)(构造函数、析构函数、拷贝构造、赋值重载)
本文深入探讨了C++类的默认成员函数,包括构造函数、析构函数、拷贝构造函数和赋值重载。构造函数用于对象的初始化,析构函数用于对象销毁时的资源清理,拷贝构造函数用于对象的拷贝,赋值重载用于已存在对象的赋值。文章详细介绍了每个函数的特点、使用方法及注意事项,并提供了代码示例。这些默认成员函数确保了资源的正确管理和对象状态的维护。
90 4
|
1月前
|
存储 编译器 Linux
【c++】类和对象(上)(类的定义格式、访问限定符、类域、类的实例化、对象的内存大小、this指针)
本文介绍了C++中的类和对象,包括类的概念、定义格式、访问限定符、类域、对象的创建及内存大小、以及this指针。通过示例代码详细解释了类的定义、成员函数和成员变量的作用,以及如何使用访问限定符控制成员的访问权限。此外,还讨论了对象的内存分配规则和this指针的使用场景,帮助读者深入理解面向对象编程的核心概念。
108 4