アルゴリズムトレーニング入試(01ナップサック問題、dp動的計画法、青いブリッジカップC ++)

テスト問題アルゴリズムトレーニング入試

リソースの制限
時間の制限:1.0秒メモリの制限:256.0MB
問題の説明Chenchen
  は才能のある子供であり、彼の夢は世界で最も偉大な医師になることです。このため、彼は近くで最も権威のある医師を教師として崇拝したかったのです。彼の適性を判断するために、医者は彼に難しい問題を提示した。医者は彼をハーブでいっぱいの洞窟に連れて行き、彼に言った:「私の子供、この洞窟にはいくつかの異なるハーブがあります。それぞれの植物を選ぶのに時間がかかり、それぞれの植物には独自の価値があります。私はそれを与えます彼。この期間中にいくつかのハーブを集めることができます。あなたが賢い子供なら、あなたは
  あなたが集めるハーブの合計値を最大にすることができるはずです。 "あなたがチェンチェンなら、あなたはこのタスクを完了することができます。
入力形式の
  最初の行には、スペースで区切られた2つの整数T(1 <= T <= 1000)とM(1 <= M <= 100)があります。Tは薬を集めるために使用できる合計時間を表します。 Mは洞窟内のハーブの数を表します。次のM行のそれぞれには、1から100までの2つの整数(1と100を含む)が含まれています。これらはそれぞれ、特定のハーブを選ぶ時間とハーブの値を示します。
出力形式に
  は1行が含まれます。この行には、指定された時間内に収穫できるハーブの最大合計値を表す整数のみが含まれます。
サンプル入力
703
71 100
69 1
1 2
サンプル出力
3
データのスケールと規則データの
  30%の場合、M <= 10、
  すべてのデータの場合、M <= 100。

はじめに:この古典的な01ナップサック問題を終えた後、私はついにこの種の動的計画法をほぼ習得したと思います。個々の問題に分解すると、0または1しかないため、なぜ01ナップサック問題と呼ばれるのですか。するかしないか)2つのケースでは、動的計画法のアイデアを使用して、答えの最良の値が最後に必要になることがよくあります。

アイデアと分析:

私が正方形の数について書いたブログのように、この問題を解決するアイデアは次のとおり
です1。たとえば、合計70分と5種類の医薬品があります:
次に、最初に配列dp [i]を使用します[j]最初のi種類の医薬品を表します-残りのj分で得られる最大値
2.次に、i == 0またはj == 0の場合、iは0に等しいため、値は0であることがわかります把握する医薬品はなく、jが0の場合は時間がないことを意味します

if(j == 0 || i == 0)
        dp[i][j] = 0;

3.現在の医薬品が残り時間より長い場合:
現在の医薬品を把握していないと見なすことができる場合、現在の医薬品は最後の医薬品の値と等しくなります。

else if(time[i] > j)
        dp[i][j] = dp[i-1][j];

4.他の場合では、現在の医薬品をつかむかどうかを選択することを考えることができますか?、つかまない場合はdp [i] [j] = dp [i-1] [j]です。つかまない場合は、最後の医薬品であり、残り時間から費やした時間を差し引いたものです。つかむ値に現在の医薬品の値を加えたものは次のとおりです。dp[i-1] [j -time [i]] + price [i]
次に、つかむ場合とつかまない場合の2つのケースの最大値を選択します。

else
        dp[i][j] = max(dp[i-1][j],dp[i-1][j -time[i]]+price[i]);

5.最後のステップは、dp [quantity] [time]を出力することです。

cout << dp[m][t];

完全なコード:

#include<bits/stdc++.h>
 using namespace std;
 int main(){
    
    
     int t,m;
     cin >> t >> m;
     int time[1002];
     int price[102];
     int dp[102][1002];
     for(int i=1;i<=m;i++)
     {
    
    
         cin >> time[i] >> price[i];
     }

     for(int i = 0;i<=m;i++)         //药草数量
     {
    
    
         for(int j=0;j<=t;j++)       //剩余时间
         {
    
    
             if(j == 0 || i == 0)
                    dp[i][j] = 0;
             else if(time[i] > j)
                    dp[i][j] = dp[i-1][j];
             else
                    dp[i][j] = max(dp[i-1][j],dp[i-1][j -time[i]]+price[i]);
         }
     }
    cout << dp[m][t];
	return 0;
 }

あとがき:たくさんのdpビデオを見た後、ようやく自分で質問できるようになりました。簡単ではありません。さようならdp、dfsQAQを学ぶ必要があります。

おすすめ

転載: blog.csdn.net/Kyrie_irving_kun/article/details/113765263