PAT1079多叉树

1079 Total Sales of Supply Chain (25分)

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. Only the retailers will face the customers. 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 total sales from all the 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 their ID’s are numbered from 0 to N−1, and the root supplier’s ID is 0); P, the unit price given by the root supplier; and r, the percentage rate of price increment for each distributor or retailer. Then N lines follow, each describes a distributor or retailer in the following format:

K**i ID[1] ID[2] … ID[K**i]

where in the i-th line, K**i is the total number of distributors or retailers who receive products from supplier i, and is then followed by the ID’s of these distributors or retailers. K**j being 0 means that the j-th member is a retailer, then instead the total amount of the product will be given after K**j. All the numbers in a line are separated by a space.

Output Specification:

For each test case, print in one line the total sales we can expect from all the retailers, accurate up to 1 decimal place. It is guaranteed that the number will not exceed 1010.

Sample Input:

10 1.80 1.00
3 2 3 5
1 9
1 4
1 7
0 7
2 6 1
1 8
0 9
0 4
0 3    

Sample Output:

42.4

题目大意:

这是一个多叉树的销售供应链,从一种商品从根节点开始有一个起始的定价price ,从根节点到最下层的零售商,每一层都会以 %r 的增长率进行加价处理 然后把货物供给下家。现在让我们计算所有的零售商手中的货物值多少钱。整个供应链的结构如下:

示意图

图中小括号中标注的是零售商手中的货物量如果用weight表示。如果我们规定根节点的深度depth = 0 ,那么,到达4号零售商,depth = 2 ,那么经过两次加价(0 --> 2 --> 4)4号手中的货物价值为 : (1+%r)^depth * weight * price。我们把所有零售商手中的货物价值加起来,就可以得到总的价值。

思路分析:

首先依然是,我们如何存储这样一课多叉树。用链式存储是比较麻烦的,由于节点的ID 是从 0 - N-1 进行编号的,同时指明了根节点是0 号, 一个很自然的想法是静态数组进行存储, 数组的每一个元素是一个Node 对象,这个对象包含了一个权重变量 weight (如果是叶子节点,我需要用来存储货物量),一个List 列表,存储当前节点的所有孩子节点是谁。

从题目给的数据格式我们可以看到,行号i 就代表节点的ID ,第 i 行的第一个数字number代表节点i 有多少个孩子节点,如果为0 ,就表示一个节点也没有,那么这个节点就是一个零售商节点,第二个数子就是这个零售商拥有的货物数量。否则的话这个节点就是一个中间商节点,后面的 number个数子都是节点 i 的孩子节点。这样,我们可以比较容易地通过数组下标映射的方式找到一个节点的孩子节点。

剩下的就是递归回溯求解的过程。通过深度优先遍历,我们从根节点开始,去遍历树中的每一个节点,当碰到一个叶子节点,也就是零售商的时候,就计算一次当前的货物价值,并累加到最后的结果上。 由于使用Java的原因,以下程序只获得了25分中的15分,4个测试点运行超时,如果有同学可以优化代码,希望可以在评论区或者私信,给予我指导。

完整代码:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

public class P1079 {
    static class Node {
        double weight; // 权重
        List<Integer> children = new ArrayList<>();// 孩子节点 这是多叉树

    }

    static Node[] nodes;
    static double res = 0;
    static double price;
    static double increase;

    public static void main(String[] args) throws IOException {
        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
        String[] TreeInfo = bf.readLine().trim().split(" ");
        int nums = Integer.parseInt(TreeInfo[0]);  // 节点个数
        price = Double.parseDouble(TreeInfo[1]);    // 货物起始价格
        increase = (Double.parseDouble(TreeInfo[2])) / 100; // 每一层加价的比率 这里换算成小数
        nodes = new Node[nums];                            // 创建节点数组  0 号节点就是根节点
        for (int i = 0; i < nums; i++) {

            String[] info = bf.readLine().trim().split(" ");
            nodes[i] = new Node();
            int cnts = Integer.parseInt(info[0]);
            if (cnts == 0) {  //  如果孩子节点的个数为0  那么这个节点就是一个零售商(叶子)节点
                nodes[i].weight = Integer.parseInt(info[1]);
            } else {   // 否则这是一个有cnts 个孩子的 中间商节点
                for (int j = 1; j <= cnts; j++) { //依次把cnts 个孩子添加进行孩子列表中
                    nodes[i].children.add(Integer.parseInt(info[j]));
                }
            }
        }
        DFS(0 , 0); //  从0号根节点开始求解,初始深度定为0 深度理解为加价的次数更应景一些
        System.out.printf("%.1f",res);


    }
	// DFS 遍历求深度,并结算结果
    static void DFS(int root, int depth) {
        if (nodes[root].children.size() == 0) { // 如果到达叶子节点 我们就计算当前值 并返回
            res += Math.pow( (1+increase) , depth)* price * nodes[root].weight;
            return;
        }
        
        int childrenNum = nodes[root].children.size(); //否则看看有多少孩子节点
        for(int i = 0 ;i< childrenNum ;i++){ // 对每一个孩子节点进行依次DFS 向下递归

            DFS(nodes[root].children.get(i) , depth+1);
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值