タイトル説明
より多くの学生が私たちのUSACOレースで得点、より多くの我々は満足しています。
我々は、人々は私たちがあなたの助けを必要とし、できるだけ多くのポイントを獲得することができるように私たちのコンテストを設計してみてください。
私たちは、同じスコアを取得するための時間と同量のエネルギーを必要とするトピックのセットを解決するために、タイトル争いのいくつかのタイプ、「種」はコンテストのトピックの集合を指しいずれかから選択することができます。あなたの仕事は、所定の時間に競争の問題を解決し、最大のスコアに合計時間を作り、各カテゴリから選択する必要がありますどのように多くの話題USACOのスタッフを、伝えるためにプログラムを書くことです。入力は、時間との競争が含まれ、M(1 <= M < = 10,000)( 長いゲームを持って、あなたがトレーニングキャンプに行き、心配しないでください)とN、1 <= N <= 10000「種」の数。各行は「ジャンル」を記述するために2つの整数の後を含む:
このトピックの最初の溶液説明整数分(1 <=ポイント<= 10000を得ることができる ) 、このトピックに対処するために必要な第2の整数命令を時間(1 <=分<= 10000 )。
あなたのプログラムは、私たちがそれぞれの「種類」からトピックを選択する必要がありますどのくらいの道を決定する必要があり、時間との戦いにおける最大のスコアを取得することが可能となります。
「タイプ」からトピックの任意の数は、任意の負でない数(0以上)であってもよいです。
最大スコアの可能なGETを計算します。
・(ここで気持ちがバックパック、qwqです参照)
エントリー
1行目:M、時間と対象N--レースの「タイプ」の数。
二つの整数:2-N + 1つの行の各々 「タイプ」のトピックのスコアと時間がかかります。
輸出
与えられた制限で最大のスコアを含む単一の行が得ることができます。
サンプル入力
300 4
100 60
250 120
120 100
35 20
サンプル出力
605
考え
この質問は、私たちは、最大のスコアの尋ねるデータ範囲のみを二次元DPで見てみましょうするものです。
\ [O(N ^ 2)問題はない、今万人を超えます。\]
- [バツ]
其实我还见过
\ [O(N ^ 2)より、それの百万より。\]
私たちは、この2次元DPを分析してみましょう:
時間は、実際にバックパックナップザック問題に変換されるコンテストトピックは容量であり、N Nは、項目を発現しました
すべては質量と体積を持っています。彼は、それが番号を選択することができるように、彼は多くて、だけでなく、グループを選択することができると述べました。実際には、これらの項目の合計値は、与えられたデータの答えです。
正解はそう完全にバックパックああです。(正確にバックパック何Baiduの百科事典を参照してください)
それの特定のポイント?
しかし、ちょっと待って。
フルバックパックについていえば。
プレイの最初の第1の2次元スタイル:
FIJ iが選択された番組は、最初のIアイテムであるかどうかを、得られたJ-容量バックパックの最大値に配置された前面または項目を設定します。
その後、状態遷移方程式を描くことができます。
これらの項目は、選択したときにするとき
f[i][j] = f[i][j-a[i]]+w[i];
置くために選挙の時には、[i]は、この時間のかかるプラスのスコアを失います。
これらの項目は、時間を選択しない場合には
f[i][j] = f[i-1][j];
彼は1最適解を保持したときに選択しないでください。
だから、コードの構造が出てきました。
for(int i = 1; i <= n ; i++){
for(int j = 1; j <= m ;j++){
if(j < a[i]) f[i][j] = f[i-1][j];
else if(f[i-1][j] > f[i][j-a[i]]+w[i]) f[i][j] = f[i-1][j];
else f[i][j] = f[i][j-a[i]]+w[i];
}
}
サイクルI - > N:
サイクルJ - >メートル
場合jは<[i]は、既に選択されていない、従って最適解を保証されます。
解決策は、現在の最適解より大きくなっている場合には、その後も、それは選択することはできません。
他の例は、選択されなければなりません。
FNM、出力それに答え。
状態遷移方程式を置くためにはじめに:
f[i][j]=max{f[i-1][j-k*c[i]]+k*w[i]|0<=k*c[i]<=j}
そして、遊びの一次元のスタイルを再訪:
時には人々が話題を嫌い、故意ので、2つの次元が、バックパック、あなたがメモリを炒めてみましょう。
遊び(前提が* 5000 5000以上である2次元配列、2次元の1次元のスタイルを使用するには、この時間REが)。
実際に、私はこの次元を持っていない、jのみ、スペースの複雑さが大幅に減少しました。
それを変更するサイクル。
1 - > N変わらず
重複を避ける> M - [i]はW
一次元の思考:
この選択した項目:
if(f[j-w[i]]+a[i] > f[j]){
f[j] = f[j-w[i]]+a[i];
}
現在の更新は前よりも大きくなります。
そうでない場合は終了します。
選挙なし:いいえ取引。
一次元コードアーキテクチャは、出てきました:
for(int i = 1; i <= n ; i++){
for(int j = w[i]; j <= m ;j++){
if(f[j-w[i]]+a[i] > f[j]){
f[j] = f[j-w[i]]+a[i];
}
}
}
上記の状態遷移方程式の総合的な外観
f[j] = max(f[j],f[j-w[i]]+a[i]);
その答えがf [m]の出力にあります。
- (ああのように、実際には、より多くの一次元の演奏よりも確かに良いです)
概要
さまざまなトピックの異なるコードを使用してください。
この質問は、メモリのために、私は前の寸法を書いています。
次元JJ 91ポイント、ああ祖先を参照してください。
最終的な分析では、これは唯一の問題テンプレートの完全なバックパックで、最終的にAグレードで1位。
- (私が弱すぎるんだけど、も... qwq)
正確にバックパックを知っていることを学びます:
[X]動的計画法は何ですか。
- [X]は、再帰的なアルゴリズムは何ですか。
- [X]メモリ検索とは何ですか。
[X]は、再帰的なアルゴリズムは何ですか。
よりよく理解するために。