POJ—3253柵の修理
説明
農夫ジョンは牧草地の周りの短い長さの柵を修理したいと思っています。彼は柵を測定し、それぞれが整数の長さのLi(1≤Li≤50,000)単位を持つN(1≤N≤20,000)の木の板が必要であることを発見しました。次に、彼はN枚の厚板をのこぎりで切るのに十分な長さのロングボードを1枚購入します(つまり、その長さはLiの長さの合計です)。FJは、おがくずが行われたときにおがくずに失われる余分な長さである「切り口」を無視しています。あなたもそれを無視するべきです。
FJは悲しいことに、自分が木を切るためののこぎりを持っていないことに気付いたので、この長いボードを持ってファーマードンズファームに行き、のこぎりを借りてもいいかと丁寧に尋ねました。
クローゼットの資本家であるファーマードンは、FJにのこぎりを貸しませんが、代わりに、厚板のN-1カットごとにファーマージョンに請求することを提案します。木片を切るための料金は、その長さとまったく同じです。長さ21の厚板を切るには21セントかかります。
次に、ファーマードンはファーマージョンに厚板を切る順序と場所を決定させます。ファーマージョンがN枚の板を作成するために費やすことができる最小金額を決定するのを手伝ってください。FJは、ボードをさまざまな順序でカットできることを知っています。これにより、結果として得られる中間の厚板の長さが異なるため、料金が異なります。
入力
1行目:1つの整数N、厚板の数
2行目…N + 1:各行には、必要な厚板の長さを表す1つの整数が含まれています
出力
1行目:1つの整数:N-1カットを行うために彼が費やす必要のある最小金額
サンプル入力
3
8
5
8
サンプル出力
34
ヒント
彼は長さ21のボードを長さ8、5、および8
の断片にカットしたいと考えています。元のボードのサイズは8 + 5 + 8 = 21です。最初のカットのコストは21で、ボードを13と8の小片にカットするために使用する必要があります。2番目のカットのコストは13で、13を8と5にカットするために使用する必要があります。これは21 + 13 = 34のコストになります。 。代わりに21を16と5にカットした場合、2番目のカットは16で、合計37(34以上)になります。
中国語の翻訳
タイトル説明
農夫ジョンは牧場の周りの柵の小さな部分を修理したいと思っています。彼は柵を測定し、それぞれがLi(1≤Li≤50000)の整数の長さを持つN(1≤N≤20000)の厚板が必要であることを発見しました。次に、彼はN枚のボードを入手するのに十分な長さのベニヤロングボードを購入しました(つまり、長さは長さLiの合計です)。ジョンは「カット」を無視します。カットして鋸で切るとき、おがくずは余分な長さを失います、そしてあなたもそれを無視するべきです。
ジョンは木を切るためののこぎりがないことに後悔して気づいたので、ファーマードンの農場に行き、のこぎりを借りてもいいかと丁寧に尋ねました。ドンはジョンにのこぎりを貸しませんでしたが、ジョンに1個あたりN-1個を切断するための切断料金を提供しました。木片を切る費用はその長さとまったく同じです。21の長さのボードを切るのに21セントかかります。
ドンはジョンにボードを切る順序と位置を決めるように頼んだ。ジョンが彼のためにN枚の板の最小量を決定するのを手伝ってください。ジョンは、ボードをさまざまな順序でカットできることを知っています。結果として得られる中間ボードの長さが異なるため、コストも異なります。
入力
行1:整数N、厚板の数。
行2。N + 1:各行には、必要な厚板の長さを表す整数が含まれています。
出力
行1:整数:彼がN-1から切る
サンプル入力
3
8
5
8
サンプル出力
34
問題解決のアイデア
この質問の本質はハフマンツリーの適用です。例として質問の例を見てください。1回のカットの後にカットされた2つのピースが13、8の場合、厚板の全長は8 + 5 + 8 = 21です。最初のカットのコストは13+ 8 = 21、次に13を5と8にカットし続けると、2番目のナイフのコストは5 + 8 = 13になります。これは前向きな考慮事項です。問題の観点から、合計n個の木材に切断するコストは、形成された二分木で新しく生成されたノードの周波数の合計です。13+21 = 34。ツリーがハフマンツリーの場合、周波数の合計が最小になります。
注意:
①N= 1の場合、コストはブロックの長さです。これがタイトルに必要なものです。他にご意見がございましたら、お
気軽にお問い合わせください。②この質問も優先キューを使用しています。よくわからない場合は、必ず戻ってこの知識をよく理解してください。クリックしてください
。③タイトルのデータの範囲に注意してください。たとえば、料金を請求する場合、intでは不十分です。私は長い間使用しています。
参照コード
#include<iostream>
#include<queue>
using namespace std;
priority_queue<int, vector<int>, greater<int> >Q;
long long total;
int main()
{
int n,len;
cin >> n;
while (n--)
{
cin >> len;
Q.push(len);
}
if (Q.size() == 1)
{
total = Q.top();
}
else
{
while (Q.size() > 1)
{
int sum = 0;
sum += Q.top();
Q.pop();
sum += Q.top();
Q.pop();
Q.push(sum);
total += sum;
}
}
cout << total<<endl;
return 0;
}