合併果子 / [USACO06NOV] Fence Repair G(貪心,優先隊列,multiset)分別實現

在這裏插入圖片描述在這裏插入圖片描述
在這裏插入圖片描述題解:此題爲貪心思想,實際上也是哈夫曼樹的一個構造問題,具體做法如下三種:

方法一
首先對果子數目按從小到大順序進行排序,將第一個果子和第二個果子的數目和計算到第二個果子中,計算體力耗費值,然後利用插入排序思想將第二個果子插入到合適位置(利用此方法可節約排序空間),然後將第二個果子和第三個果子的數目和計算到第三個果子中,重複以上操作,可得最小體力耗費值
代碼實現

#include<iostream>
#include<algorithm>
using namespace std;
int array[10005];
int main(){
	int n,Strength=0;
	cin>>n;
	//輸入數組 
	for(int i=0;i<n;i++){
		cin>>array[i];
	}
	//首次排序,目的從前開始向後合併 
	sort(array,array+n);
	//n-1次合併
	for(int i=0;i<n-1;i++){
		//將i合併到i+1
		array[i+1]=array[i]+array[i+1];
		//計算體力消耗值
		Strength+=array[i+1];
		//將合併後的值插入到合適位置
		int fg=array[i+1];//臨時保存待插入值 
		int j=i+1;
		while(j<n-1){
			if(fg<=array[j+1]){//找到了合適的位置插入 
				break;
			}else{
				array[j]=array[j+1];//移動
				j++; 
			} 
			
		} 
		//插入 
		array[j]=fg;
	} 
	//輸出力量值 
	cout<<Strength;
	return 0;
} 

方法二
利用C++STL庫中的優先隊列,此題便成爲了送分題,因爲優先隊列具有自動排序功能,每次取隊首兩個數,計算和壓入隊列中,並使他們出隊,直到隊列還剩一個數
優先隊列可參考:優先隊列詳解
代碼實現:

#include<iostream>
#include<queue>
using namespace std; 
int main(){
	//定義小頂堆 
	priority_queue <int,vector<int>,greater<int> >q;
	int n,t,heaving=0;
	cin >> n;
	//輸入果子數目 
	for(int i=0;i<n;i++){
		cin >> t;
		q.push(t);//壓入隊列中 
	}
	//合併果子 
	while(q.size()>1){
		//取前兩個最小堆 
		int t1 = q.top();
		q.pop();
		int t2 = q.top();
		q.pop(); 
		q.push(t1+t2);//將新堆壓入隊列 
		heaving+=t1+t2;//計算消耗體力值 
	}
	cout<<heaving<<endl;
	return 0;
} 

方法三:
利用C++STL庫中的multiset集合進行解題
具體使用可參考:multiset使用詳解
具體代碼實現思路與上述方法二類似

#include<iostream>
#include<set>
using namespace std;
int main(){
	multiset< int > set1;//定義集合 
	int n,t,heaving=0;
	cin>>n;
	//輸入果子數存入集合 
	for(int i=0;i<n;i++){
		cin >> t;
		set1.insert(t);
	}
	//開始合併堆 
	while(set1.size()>1){//保證剩餘1堆 
		int m1=*set1.begin();//獲取最小堆
		set1.erase(set1.begin());//將最小堆刪除
		int m2=*set1.begin();//獲取第二小堆
		set1.erase(set1.begin());//將第二小堆移除
		heaving+=m1+m2;//計算體力消耗值
		set1.insert(m1+m2);
	}
	//輸出最小消耗值 
	cout<<heaving<<endl;
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章