果樹園では、ダダはすでにすべての果物をノックダウンし、果物の種類に応じてそれらをさまざまな山に分けていました。
ダダはすべての果物を1つの山にまとめることに決めました。
それがマージされるたびに、ダダは2つの果物の山を一緒にマージすることができ、消費されるエネルギーは2つの果物の山の重量の合計に等しくなります。
すべての果物がn-1回マージされた後、残っている山は1つだけであることがわかります。
果物をマージするときにダダが消費するスタミナの合計は、各マージで消費されるスタミナの合計に等しくなります。
これらの果物を家に戻すには多大な労力がかかるため、ダダは果物をマージするときにできるだけ多くのエネルギーを節約する必要があります。
各果物の重量が1であり、果物の種類の数と各果物の数がわかっていると仮定すると、目標を達成するために必要な物理的な労力と出力を最小限に抑えるための組み合わせシーケンス計画を設計することがタスクです。身体的努力の最小値。
たとえば、果物は3種類あり、その数は1、2、9です。
最初に杭1と2をマージでき、新しい杭の数は3で、物理的な労力は3です。
次に、新しいパイルを元の3番目のパイルとマージし、番号が12で物理的な労力が12の新しいパイルを取得します。
したがって、ダダは合計で体力= 3 + 12 = 15を消費します。
15が最小の物理的コストであることが証明できます。
入力形式
入力は2行で構成され、最初の行は整数nで、果物の種類の数を示します。
2行目には、スペースで区切られたn個の整数が含まれています。i番目の整数aiは、i番目の果物の数です。
出力形式
出力は1行で構成され、この行には最小の身体運動値である整数のみが含まれます。
この値が231未満であることを確認するためにデータを入力します。
データ範囲
1≤n≤10000、
1≤ai≤20000
入力例:
3
1 2 9
サンプル出力:
15
アイデア
これは二分木と見なされます。ルートノードから最も遠い数(加算回数)が最もマージされるため、最初に最小の2つのポイントが選択され、次にこれら2つのポイントのルートノードになります。ポイントは最小の2つのポイントから選択され、継続的に更新され、最終的にパイルにマージされます。
主なアイデア
ハフマンツリー
この問題を解決するには、スモールルートヒープを使用する必要があります。スモールルートヒープは、最小の2つのツリーを見つけて、ヒープを更新します。ヒープのサイズが最終的に1に更新されると、マージが終了し、計算する必要があります。マージの消費。
この質問は石の結合と非常に似ていますが、石の結合は隣接する石です。この結合は必ずしも隣接しているとは限らず、ランダムです。
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
int main(void)
{
int n;
cin>>n;
priority_queue<int,vector<int>,greater<int>> heap;
while(n--)
{
int w;
cin>>w;
heap.push(w);
}
int res=0;
while(heap.size()>1)
{
int a=heap.top();
heap.pop();
int b=heap.top();
heap.pop();
res+=a+b;
heap.push(a+b);
}
cout<<res;
}