# Priority Queue# Greedy# Heap

b151 - NOIP2004 2.合并果子

🔗 前往 ZeroJudge 原題

題目描述

題目要求計算將 n 堆果子合併成一堆時,總共消耗的最少體力。每次合併兩堆果子,消耗的體力等於兩堆果子的重量之和。果子重量都為 1,給定每種果子的數量,求最小的總體力消耗。

解題思路

這個問題可以使用貪心演算法解決。每次合併體力消耗最小的兩堆果子,直到只剩下一堆。使用優先佇列(小根堆)來存儲每堆果子的數量,每次取出最小的兩個,合併後再放回優先佇列。重複此過程直到優先佇列中只剩一個元素。

複雜度分析

  • 時間複雜度: O(n log n) (n 是果子的種類數,每次 pop 和 push 優先佇列的複雜度都是 log n,總共需要 n-1 次合併操作)
  • 空間複雜度: O(n) (優先佇列需要存儲所有果子的數量)

程式碼

#include <iostream>
#include <queue>
using namespace std;
int n,tmp;
int main(){
	cin.tie(0); ios::sync_with_stdio(false);
	while(cin >> n){
		priority_queue< int,vector<int>,greater<int> > a;
		for(int i=0;i<n;++i){
			cin >> tmp;
			a.push(tmp);
		}
		long long int ans=0;
		for(int i=1;i<n;++i){
			int x=a.top();
			a.pop();
			int y=a.top();
			a.pop();
			x+=y;
			ans+=x;
			a.push(x);
		}
		cout << ans << "\n";
	} 
}

Discussion