[解決済み】過積載の飛行機から一番太っている人を放り出す。
質問
例えば、ある飛行機が燃料不足になったとします。 乗客の体重3000ポンドを落とさない限り、飛行機は次の空港に到着することができない。 最大限の人命を救うために、体重の重い人を先に飛行機から投げ捨てたいと思います。
そうそう、飛行機には何百万人もの人が乗っているので、必ずしもリスト全体をソートすることなく、最も重い乗客を見つける最適なアルゴリズムが欲しいのです。
これは、私がC++でコーディングしようとしているものの代理問題です。 私は乗客名簿を重量で部分的にソートしたいのですが、必要な要素の数がわかりません。 私自身の "partial_sort" アルゴリズム ("partial_sort_accumulate_until") を実装することができますが、標準 STL を使用してこれを行う簡単な方法があるかどうか疑問に思っています。
どのように解決するのですか?
一つの方法として
ミニヒープ
(
std::priority_queue
C++の場合)。以下は、その方法です。
MinHeap
クラスがあります。 (そう、この例はC#で書いています。)
int targetTotal = 3000;
int totalWeight = 0;
// this creates an empty heap!
var myHeap = new MinHeap<Passenger>(/* need comparer here to order by weight */);
foreach (var pass in passengers)
{
if (totalWeight < targetTotal)
{
// unconditionally add this passenger
myHeap.Add(pass);
totalWeight += pass.Weight;
}
else if (pass.Weight > myHeap.Peek().Weight)
{
// If this passenger is heavier than the lightest
// passenger already on the heap,
// then remove the lightest passenger and add this one
var oldPass = myHeap.RemoveFirst();
totalWeight -= oldPass.Weight;
myHeap.Add(pass);
totalWeight += pass.Weight;
}
}
// At this point, the heaviest people are on the heap,
// but there might be too many of them.
// Remove the lighter people until we have the minimum necessary
while ((totalWeight - myHeap.Peek().Weight) > targetTotal)
{
var oldPass = myHeap.RemoveFirst();
totalWeight -= oldPass.Weight;
}
// The heap now contains the passengers who will be thrown overboard.
標準的な文献によると、ランニングタイムは、以下の値に比例します。
n log k
ここで
n
は乗客の数であり
k
はヒープ上のアイテムの最大数である。乗客の体重が通常100ポンド以上であると仮定すれば、ヒープに30個以上のアイテムが含まれることはまずないでしょう。
最悪のケースは、乗客が重量の小さいものから大きいものへと順に表示される場合です。その場合、すべての乗客をヒープに追加し、すべての乗客をヒープから削除する必要があります。それでも、100万人の乗客がいて、最も軽い人の体重を100ポンドと仮定すると、この場合
n log k
は、それなりに小さい数字になります。
乗客の重みをランダムに取得すれば、パフォーマンスはもっと良くなります。私はこれに似たものをレコメンデーションエンジンに使っています(数百万件のリストから上位200件を選択する)。実際にヒープに追加されるアイテムは、通常5万から7万個程度です。
ヒープ上の最も軽い人よりも軽いので、候補者の大半が却下されるのです。そして
Peek
は
O(1)
演算を行う。
ヒープセレクトとクイックセレクトの性能について詳しくは 理論と実践が出会うとき . 簡単に説明すると、選択する項目が全体の1%未満であれば、ヒープ選択がクイック選択より明らかに勝っています。1%以上であれば、クイック選択か、以下のようなバリエーションを使用します。 イントロセレクト .
関連
-
[解決済み】fpermissiveフラグは何をするのですか?
-
[解決済み】「Expected '(' for function-style cast or type construction」エラーの意味とは?
-
[解決済み】1つ以上の多重定義されたシンボルが見つかる
-
[解決済み] explicit キーワードの意味は?
-
[解決済み] 辞書のリストを辞書の値でソートするにはどうしたらいいですか?
-
[解決済み] ルール・オブ・スリーとは?
-
[解決済み] コピーアンドスワップ慣用句とは?
-
[解決済み] なぜテンプレートはヘッダーファイルでしか実装できないのですか?
-
[解決済み] ゲーム「2048」の最適なアルゴリズムとは?
-
[解決済み】C/C++の"-->"演算子とは何ですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] エラーが発生する。ISO C++は型を持たない宣言を禁じています。
-
[解決済み】 != と =! の違いと例(C++の場合)
-
[解決済み】Cygwin Make bash コマンドが見つかりません。
-
[解決済み】エラー。switchステートメントでcaseラベルにジャンプする
-
[解決済み] 式はクラス型を持つ必要があります。
-
[解決済み] [Solved] インクルードファイルが開けません。'stdio.h' - Visual Studio Community 2017 - C++ Error
-
[解決済み】CMakeエラー at CMakeLists.txt:30 (project)。CMAKE_C_COMPILER が見つかりませんでした。
-
[解決済み] 解決済み] `pthread_create' への未定義の参照 [重複] [重複
-
[解決済み】C++ - 適切なデフォルトコンストラクタがない [重複]。
-
[解決済み】Visual Studioのデバッガーエラー。プログラムを開始できません 指定されたファイルが見つかりません