首页 > 试题广场 >

Highest Price in Supply Chain

[编程题]Highest Price in Supply Chain
  • 热度指数:7353 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 64M,其他语言128M
  • 算法知识视频讲解
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.

输入描述:
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 Si 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.


输出描述:
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.
示例1

输入

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

输出

1.85 2
用的最无脑的方法。。
#include <stdio.h>
#include <math.h>
int main(void) {
    int n, i, x;
    int max = 0, mcount = 0, count;	
    double p, r;

    static int id[100000];
    
    scanf("%d%lf%lf", &n, &p, &r);
    for (i = 0; i < n; i++) {
        scanf("%d", &id[i]);        
    }
    for (i = 0; i < n; i++) {
        x = i;
		count = 0;
        while (id[x] != -1) {
            x = id[x];
            count++;           
        }
        if (count > max) {
            max = count;
            mcount = 1;
        }
        else if (count == max) {
            mcount++;
        }                
    }
    printf("%.2f %d\n", p*pow(r/100+1, max), mcount);
    
    return 0;
}

编辑于 2017-08-01 18:03:23 回复(4)
import java.util.*;
import java.math.*;

public class Main{
    public static void main(String[] args){
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        double p=sc.nextDouble();
        double r=sc.nextDouble();
        ArrayList<Integer> list=new ArrayList<Integer>();
        for(int i=0;i<n;i++){
            list.add(sc.nextInt());
        }
        int count=0;
        int depth=-1;
        for(int i=0;i<list.size();i++){
            int index=i;
            int tmpDepth=0;
            while(list.get(index)!=-1){
                index=list.get(index);
                tmpDepth++;
            }
            if(tmpDepth>depth){
                depth=tmpDepth;
                count=1;
            }else if(tmpDepth==depth){
                count++;
            }
        }
        System.out.printf("%.2f %d",p*Math.pow((100.00+r)/100,depth),count);
    }
}

发表于 2018-10-02 15:20:29 回复(0)
 题目大意呢,有一堆商人,其中除了一个最基础的供应商,其他的都必须从上一层供应商那里拿货,只有最终的销售商才卖东西,然后让我们算最贵的销售商在哪里。

      这道题目呢,如果建模比如A从B那里拿货,你就画一条从A指向B的线,最终会构成一个图,而且所有的线最终会指向那个题目中的“root supplier”,我们的目标是在这张图中找最长路。然后注意一下保存已经搜索过的答案就好了。

      还有一个方法并是DFS搜索,反正所有的线都是从根节点开始的,我们建图的时候就不要保存某某节点的祖先是谁了,直接保存某某节点的孩子是谁把,然后从根节点开始搜索,同时保存最长距离,最后扫描一次输出。不过我没试过。

      

# include <cstdio>
# include <iostream>
# include <cstring>
# include <cmath>
# include <algorithm>
using namespace std;

const int _size = 100000;
int chain[_size];
int lenth[_size];
int GetLenth(int i)
{
	if (lenth[i]!=-1)
	    return lenth[i];
    if (chain[i]==-1)
        return lenth[i] = 0;
    else 
        return lenth[i] = GetLenth(chain[i]) + 1; 
}
int main()
{
  memset(lenth,-1,sizeof(lenth));
  int n;
  double p,r;
  cin >> n >> p >> r;
  for (int i=0;i<n;i++)
      cin >> chain[i];
  int Max = -1;
  for (int i=0;i<n;i++)
      Max = max(GetLenth(i),Max);
  int count = 0;
  for (int i=0;i<n;i++)
      if (lenth[i]==Max)
          count++; 
  printf("%.2lf %d\n",p*pow(1+r/100,Max),count);
  return 0;
}


发表于 2015-09-09 19:16:07 回复(0)
//爆搜dfs
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn=1e5+5;
int n,root,anscnt=0;double p,r;
vector<int> G[maxn];
map<int,int> mp;
 
void dfs(int cur,int step){
    int ok=1;
    for(int i=0;i<G[cur].size();++i){
        int v=G[cur][i];ok=0;
        dfs(v,step+1); 
    }
    if(ok){
        if(step>anscnt){
            anscnt=step;++mp[anscnt];return ;
        }
        if(step==anscnt){
            ++mp[anscnt];return ;
        }
    }
}
int main(){
    scanf("%d %lf %lf",&n,&p,&r);
    for(int i=0,tmp;i<n;++i){
        scanf("%d",&tmp);
        if(tmp==-1){ root=i;continue;}
        G[tmp].push_back(i);
    }
    dfs(root,0);    
    printf("%.2f %d\n",p*pow(1+r*0.01,anscnt),mp[anscnt]);
    return 0;
} 

发表于 2018-03-02 10:35:41 回复(2)

不需要递归。

从每个叶子节点开始,自底向上更新高度和高度的重数。最后根节点高度的重数就是卖最高价的销售商个数。

#include <cstdio>
#include <cstdlib>
#include <cmath>

int main(){
    const int MAXN = 100100;
    int parent[MAXN], height[MAXN] = {0}, num[MAXN] = {0}; //父节点,高度,重数

    int N, root;
    double p, r;
    scanf("%d %lf %lf", &N, &p, &r);
    for(int i = 0; i < N; i ++){
        scanf("%d", parent + i);
        if(parent[i] == -1) root = i;
    }

    int nh, pos, pnt; //new height
    for(int i = 0; i < N; i ++){
        if(height[i] == 0){ //还是叶子节点
            nh = 1;
            pos = i; 
            pnt = parent[i];
            while(pnt >= 0 && height[pnt] <= nh){
                if(height[pnt] == nh){
                    num[pnt] ++; //加一重
                }else{
                    height[pnt] = nh; //更新高度
                    num[pnt] = 1; //只有一重
                }
                pos = pnt;
                pnt = parent[pnt];
                nh ++;
            }
        }
    }

    double hp = p * pow(1 + r / 100, height[root]);
    printf("%.2lf %d", hp, num[root]);

    return 0;
}
发表于 2017-11-23 23:13:26 回复(0)
#include <iostream>
#include <math.h>
using namespace std;
//使用递归调用找到root supply
void findsupply(int mb[],int i,int *time){
    if(mb[i]!=-1){
        *time = *time +1;
        findsupply(mb,mb[i],time);
    }
    else return;
}
int main(){
    int N;
    double P=0,R=0;
    cin>>N>>P>>R;
    int members[N];
    for (int i=0;i<N;i++){
        cin>>members[i];
    }
    int maxtime=0;
    int time = 0;
    int tarry[N];
    for (int i=0;i<N;i++){
        findsupply(members,i,&time);
        if(time >maxtime)
            maxtime = time;
        tarry[i]= time;
        time = 0;
    }
    int n=0;
    for (int i=0; i<N; i++) {
        if (maxtime==tarry[i])
            n++;
    }
    printf("%.2f %d",P*pow(R/100+1, maxtime),n);
}
//递归

编辑于 2016-11-12 21:57:37 回复(0)
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
public class Main{
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        while (in.hasNext()) {//注意while处理多个case
        	int n = in.nextInt();//the total number of the members in the supply chain (供应链)
        	double p = in.nextDouble();//the price given by the root supplier;
        	double r = in.nextDouble()/100;//每个零售商或经销商的价格增长率
        	Node[] nodes = new Node[n];
        	Node root = null;
        	for(int i = 0;i<n;i++){
        		int parent = in.nextInt();
        		nodes[i] = new Node(parent);
        		if(parent==-1)
        			root = nodes[i];
        	}
        	for(int i = 0;i<n;i++){
        		if(nodes[i].parent!=-1){
        			nodes[nodes[i].parent].addChild(nodes[i]);
        		}
        	}
        	int d = -1;
        	int retailers = 0;
        	Queue<Node> queue = new LinkedList<Node>();
        	queue.add(root);
        	while(!queue.isEmpty()){
        		d++;
        		int size = queue.size();
        		retailers = size;
        		while(size--!=0){
        			Node top = queue.poll();
            		for(int i = 0;i<top.count;i++){
            			queue.add(top.getChild(i));
            		}
        		}
        	}
        	p *= Math.pow(1+r, d);
        	System.out.printf("%.2f %d\n",p,retailers);
        }
    }
    private static class Node{
    	int parent;
    	int count;
    	ArrayList<Node> children;
		public Node(int parent) {
			this.parent = parent;
			this.children = new ArrayList<Node>();
		}
		public void addChild(Node node){
			children.add(node);
			count++;
		}
		public Node getChild(int i){
			if(i>=children.size())
				return null;
			return children.get(i);
		}
    }
}
编辑于 2016-06-27 09:10:21 回复(0)
 
有向无环图<=>树,所以根据题意,任务实质上就是寻找最深层叶节点的层次与个数,而题目给出的是“父亲树”,从每个节点向上寻找父亲的过程中记录深度即可。
#pragma warning (disable: 4996)
#include <cstdio>
#include <cstdlib>

#include <iostream>
#include <vector>
#include <string>
#include <map>
using namespace std;

#define MAX 100005

int N; double P, r;
int parent[MAX];
map<int,int> depth;

double pMax; int dMax = 0;
vector<int> iMax;
int main()
{
	cin >> N >> P >> r;
	pMax = P;
	fill(parent, parent + N + 100, -2);
	for (int i = 0; i < N; ++i)cin >> parent[i];

	int p, cnt = 0;
	for (int i = 0; i < N; ++i) {
		p = parent[i];
		while (1) {
			if (!depth[p] && p != -1) {
				++cnt; p = parent[p];
			}
			else {
				depth[i] = cnt + depth[p] + 1;
				if (dMax <= depth[i]) {
					if (dMax < depth[i])iMax.clear();
					iMax.push_back(i);
					dMax = depth[i];
				}
				break;
			}
		}
		cnt = 0;
	}

	for (int i = 0; i < dMax - 1; ++i) {
		pMax *= (1.0 + r / 100.0);
	}

	printf("%.2f", pMax);
	cout << " " << iMax.size();
	return 0;
}


发表于 2021-01-18 00:49:33 回复(0)
用map<int, vector<int>> 模拟树的实现 使用dfs求出树的最大深度 结果保存在vector<pair<int, int>>中
#include<iostream>
(720)#include <vector>
#include <map>
(747)#include <algorithm>

using namespace std;

map<int, vector<int>> dealer_hash;
int max_depth = 0;

bool is_leafnode(int index)
{
	if (dealer_hash.find(index) == dealer_hash.end())
		return true;
	return false;
}

vector<pair<int, int>> leaf_node;

void bfs(int index, int deep)
{
	if (is_leafnode(index))
	{
		leaf_node.push_back({ index, deep });
		max_depth = max(max_depth, deep);
	}
	else
	{
		vector<int> v = dealer_hash[index];
		for (auto idx : v)
			bfs(idx, deep + 1);
	}
}

int main()
{
	int n;
	double p, r;
	cin >> n >> p >> r;
	for (int i = 0; i < n; i++)
	{
		int x; cin >> x;
		dealer_hash[x].push_back(i);
	}
	bfs(-1, -1);
	int cnt = 0;
	for (auto leaf : leaf_node)
	{
		//printf("leaf=%d deep=%d\n", leaf.first, leaf.second);
		if (leaf.second == max_depth)
			cnt++;
	}
	while (max_depth != 0)
	{
		p *= (r + 100) / 100;
		max_depth--;
	}
	printf("%.2f %d\n", p, cnt);
}

发表于 2020-03-26 20:02:37 回复(0)
pta上偶尔不再超时,可以全过了
def main():
    a = list(map(eval,input().split()))
    d,j,k,m = {},0,-2,[-1]
    for i in list(map(int,input().split())):
        try:
            d[i].append(j)
        except:
            d[i] = [j]
        j += 1
    while m:
        l,n = 0,[]
        for i in m:
            try:
                n.extend(d[i])
            except:
                l += 1
        m,k = n,k + 1
        
    print("{:.2f}".format(a[1] * (1 + a[2] / 100) ** k),l)
main()

编辑于 2020-03-29 17:15:42 回复(0)
#include <iostream>
#include <queue>
#include <vector>
#include <cmath>
using namespace std;
const int maxn=100010;
int n,num,root,maxlevel=0,maxnum=0;
double rootprice,increase;
vector<int> Node[maxn];             //存放树
void DFS(int now,int level){
    if(Node[now].size()==0){        //当前为叶结点
        if(level>maxlevel){
            maxlevel=level;
            maxnum=1;
        }
        else if(level==maxlevel)
            maxnum++;
    }
    for(int i=0;i<Node[now].size();i++)  //递归访问结点now的字结点
        DFS(Node[now][i],level+1);
    }
int main(){
    cin>>n>>rootprice>>increase;
    increase=increase/100+1;
    for(int i=0;i<n;i++){
        cin>>num;
        if(num==-1) root=i;             //根结点无父结点
        else Node[num].push_back(i);
    }
    DFS(root,0);
    printf("%.2f %d",rootprice*pow(increase,maxlevel),maxnum);
    return 0;
} 

编辑于 2019-01-17 17:13:41 回复(0)
try:
    while True:
        n,p,r = list(map(float,input().split()))
        nodes = list(map(int,input().split()))
        result = []
        for node in nodes:
            index = 0
            while node != -1:
                index += 1
                node = nodes[node]
            result.append(round(p*(r/100+1)**index,2))
        print('%.2f %d'%(max(result),result.count(max(result))))
except Exception:
    pass
编辑于 2018-11-18 22:38:22 回复(0)
#include <iostream>
#include <cstdio>
#include <cmath>

using namespace std;

int main()
{     int n,x,Max=0,max_cnt=0,cnt,a[100010];     double p,r;     cin>>n>>p>>r;     for(int i=0;i<n;i++)         cin>>a[i];     for(int i=0;i<n;i++)     {         x = i;         cnt = 0;         while(a[x] != -1)         {             x = a[x];             cnt++;         }         if(cnt > Max)         {             Max = cnt;             max_cnt = 1;         }else if(cnt == Max)             max_cnt++;     }     printf("%.2f %d\n", p*pow(1+r/100, Max), max_cnt);     return 0;
}

发表于 2018-02-07 01:34:21 回复(0)
如果只有一个结点,为什么卖出最高价的供应商数量为什么不是1?
发表于 2023-02-18 22:38:02 回复(0)
#include<bits/stdc++.h>
using namespace std;

const int Max=1e5+10;
vector<int> child[Max];
int n,maxdepth,num;
double p,r;

void DFS(int index,int depth) {
	if(child[index].size()==0) {
		if(depth>maxdepth) {
			maxdepth=depth;
			num=1;
		} else if(depth==maxdepth) {
			num++;
		}
		return ;
	}
	for(int i=0; i<child[index].size(); i++) {
		DFS(child[index][i],depth+1);
	}
}

int main() {
	int father,root;
	scanf("%d %lf %lf",&n,&p,&r);
	r/=100;
	for(int i=0; i<n; i++) {
		scanf("%d",&father);
		if(father==-1) root=i;
		else child[father].emplace_back(i);
	}
	DFS(root,0);
	printf("%.2f %d\n",p*pow(1+r,maxdepth),num);
	return 0;
}

发表于 2022-11-23 21:27:58 回复(0)
#include<iostream>
#include<vector>
#include<iomanip>
#include<cmath>
using namespace std;

struct node{  //tree node for forest
	int name;
	node* head;
};

int main(){
	int n;
	double price, rate;
	cin>>n>>price>>rate;
	vector<int> data(n);
	int temp,temp2;
	node* root;
	root=new node;
	root->name=-1;
	root->head=NULL;
	for(int i=0;i<n;i++){
		cin>>data[i];
	}
	vector<node*> node_list(n);
	node* tp;
	for(int i=0;i<n;i++){
		tp=new node;
		tp->name=i;
		node_list[i]=tp;
	}
	for(int i=0;i<n;i++){
		if(data[i]!=-1){
			tp=node_list[i];
			temp2=data[i];
			tp->head=node_list[temp2];
		}
		else{
			tp=node_list[i];//must use tempo variable to get the data from vector 
			tp->head=root;
		}
	}
	int len;int max_len=0;int max_len_pos=0;int total_count=0;
	for(int i=0;i<n;i++){
		tp=node_list[i];
		len=0;
		while(tp->head!=NULL){
			//cout<<tp->name<<" ";//
			tp=tp->head;
			len++;
		}
		if(len>max_len){
			max_len=len;
			max_len_pos=i;
			total_count=1;
		}
		else if(len==max_len)total_count++;
		//cout<<len<<" "<<max_len<<" "<<max_len_pos<<endl;//
	}
	double highest_price=price*pow(rate/100+1, max_len-1);
	cout<<fixed<<setprecision(2)<<highest_price;
	cout<<" ";
	cout<<total_count;
//	cout<<endl<<max_len;
	return 0;
}
发表于 2021-08-06 00:43:57 回复(1)
#include <iostream>
#include <iomanip>
using namespace std;
bool b[100001] = { 0 };
float price(int *a, int x, float p, float r) {
    b[x] = 1;
    if (x == -1)return p;
    return price(a, a[x], p, r)*(1 + r * 0.01);
}
int main() {
    int n, a[100001], num = 0;
    float p, r, temp, max = 0;
    cin >> n >> p >> r;
    for (int i = 0; i < n; i++) {
        cin >> a[i];
    }
    for (int i = 0; i < n; i++) {
        if (b[i] != 1) {
            temp = price(a, i, p, r);
            if (max < temp) {
                num = 1;
                max = temp;
            }
            else if (max == temp)num++;
        }
    }
    cout << fixed << setprecision(2) << max / (1 + r * 0.01);
    cout<< ' ' << num << endl;
}
发表于 2021-03-07 18:57:05 回复(0)
还行!!
#include<cstdio>
#include<vector>
using namespace std;
double ans=0,inf=-1,rate,price;
int n,root=0,u,cnt=0;
vector<int> tree[100010];
void dfs(int root,double pri){
	if(tree[root].size()==0){
		if(pri>inf) 
			inf=pri,cnt=1;
		else if(pri == inf) cnt++;
		return ;
	}
	for(int i=0;i<tree[root].size();i++)
		dfs(tree[root][i],pri*(1+rate));
}
int main(){
	scanf("%d%lf%lf",&n, &price, &rate);
	rate/=100;
	for(int i=0;i<n;i++){
		scanf("%d", &u);
		if(u==-1) root=i;
		else tree[u].push_back(i);
	}
	dfs(root,price);
	printf("%.2f %d",inf,cnt);
	return 0;
}

发表于 2021-01-30 17:05:59 回复(0)
#include<bits/stdc++.h>
using namespace std;
int n, root, Mlevel = 0, visit[100005] = { 0 }, levels[100005] = { 0 };
double p, r;
vector<int> tree[100005];
void dfs(int r, int level) {
    if (level > Mlevel) Mlevel = level;
    levels[level]++;
    for (int i = 0; i < tree[r].size(); i++) dfs(tree[r][i], level + 1);
}
int main() {
    cin >> n >> p >> r;
    for (int i = 0; i < n; i++) {
        int tp;
        cin >> tp;
        if(tp != -1)tree[tp].push_back(i);
        else root = i;
    }
    dfs(root, 0);
    double ans = p * pow(1 + r / 100, Mlevel);
    printf("%.2lf %d", ans, levels[Mlevel]);
    return 0;
}
发表于 2020-07-21 23:10:26 回复(0)
树形DP 自底向上统计以x为根的子树内答案
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 1e5 + 50;
vector<int> v[N];
double p, r;
double maxprice[N];
int maxpricecnt[N];
void dp(int x, int step)
{
    if (v[x].size() == 0)
    {
        maxprice[x] = p * pow(r, step);
        maxpricecnt[x] = 1;
        return;
    }
    for (auto y : v[x])
    {
        dp(y, step + 1);
        if (maxprice[y] > maxprice[x])
            maxprice[x] = maxprice[y], maxpricecnt[x] = maxpricecnt[y];
        else if (maxprice[y] == maxprice[x])
            maxpricecnt[x] += maxpricecnt[y];
    }
}
int main()
{
    //ios::sync_with_stdio(false);
    //cin.tie(0);
    int n, rt;
    scanf("%d %lf %lf", &n, &p, &r);
    r = 1.0 + r / 100.;
    for (int i = 0, fa; i < n; i++)
    {
        scanf("%d", &fa);
        if (fa == -1)
            rt = i;
        else
            v[fa].push_back(i);
    }
    dp(rt, 0);
    printf("%.2lf %d\n", maxprice[rt], maxpricecnt[rt]);
#ifndef ONLINE_JUDGE
    system("pause");
#endif
    return 0;
}


编辑于 2020-05-17 12:22:36 回复(0)