PAT-A-1079 Total Sales of Supply Chain (25 分) BFS廣度優先搜索 C++題解

1079 Total Sales of Supply Chain (25 分)

題目傳送門:1079 Total Sales of Supply Chain (25 分)

一、題目大意

商品銷售鏈上有供應商、經銷商、零售商,供應商以原價P將商品賣給經銷商或者零售商,而經銷商將會價格提高r%再賣給下一級的經銷商或者零售商。零售商從上一級買到商品後,也會將價格提高r%,然後直接賣給用戶。題目保證每一級的人都只有一個上級。

轉化成模型就是一棵有根多叉樹,其中供應商是樹根,經銷商是非葉子節點,零售商是葉子節點。題目要求零售商(葉子節點)的收益,也就是到所有零售商這一級時,它的售價*數量的和。

二、解題思路

這道題用DFS或者BFS都好寫,不過N達到10^5, 我怕用DFS寫會超時或者棧溢出,所以用BFS。由於慣性思維之前寫BFS時用優先級隊列較多,其實本題不需要用優先級隊列,直接用普通隊列即可。因爲所有的葉子節點都得訪問到,且所有節點的價格均爲它父節點價格的(1+r%)倍,所以其實直接使用普通隊列模擬也是可以的,我用優先級隊列多此一舉了。

先將根節點入隊,根節點的價格是p(我剛開始忽略了這一點,所以在第二組數據中n爲1時WA了,修正了此處後就AC了)。然後遍歷隊列的頭,並且依次出隊。判斷如果隊列的頭結點是葉子節點,則統計售價*數量,如果不是葉子節點,則判斷它有哪些子節點,讓他的子節點的p在當前頭結點的p基礎上乘(1+r%),然後入隊

注意用一個book數組標記結點的訪問情況,保證結點不要被重複訪問。

三、AC代碼

#include<bits/stdc++.h>
using namespace std;
struct Node
{
	int id, leaf, tot;// leaf爲1表示是葉子節點,爲0表示是非葉子節點。tot表示當leaf時產品的數量
	double p;
	bool operator<(const Node & that)const{
		if(p != that.p)
		return p < that.p;
		return id < that.id;
	}
};
int main(){
	int n;
	double p, r;
	scanf("%d %lf %lf", &n, &p, &r);
	vector<int>M[n];// 存儲每個節點有哪些子節點
	vector<Node>nodes(n);// 存儲每個節點的信息
	for(int i = 0; i < n; i++){
		int t;
		scanf("%d", &t);
		Node node;
		node.id = i;
		if(t){
			while(t--){
				int x;
				scanf("%d", &x);
				M[i].push_back(x);
			}
			node.leaf = 0;
		}else{
			cin >> node.tot;
			node.leaf = 1;
		}
		nodes[i] = node;
	}
	nodes[0].p = p;
	vector<int>book(n);
	priority_queue<Node>Q;// 本題其實只需要按層遍歷即可,沒有優先級要求,不用priority_queue就只用普通的queue也行
	Q.push(nodes[0]);
	double result = 0;
	while(Q.size()){
		Node head = Q.top();
		Q.pop();
		if(book[head.id])continue;
		if(head.leaf){
			result += head.tot * head.p;
		}
		book[head.id] = 1;
		for(auto i: M[head.id]){
			Node node = nodes[i];
			node.p = head.p*(1+r/100);
			Q.push(node);
		}
	}
	printf("%.1f\n", result);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章