最近、動的プログラミングについて読んでいます。ゼロから始めて、現在DPの問題を特定して解決することに長けている人からの連絡を希望します。私はこれらの問題をDPとして特定し、簡潔な解決策を組み立てるのに苦労しています。
私は初心者向けDPの問題とMITリソースなど)のほとんどを経験しました
私は物理学の出身なので、たくさんの数学を学んでいます。 帰納法による証明との類似点を見つけることにより、再帰的/動的プログラミングソリューションに適した問題を簡単に見つけることができます。
帰納法による証明では、2つの部分があります。
再帰的プログラミング/動的プログラミングでは:
したがって、他の人が答えたように、それは経験とヒントの選択の問題ですが、他のスキルを再利用してガイドすることができます。その後、私が述べた2つの部分を常に持つ必要があります。そうしないと、機能しません。
たとえば、セットのすべての順列を生成するには:
ほとんどの動的プログラミング問題は、メモ化によって解決できます。メモ化は通常、より直感的でコーディングが簡単です。 DPの代わりにメモ化の観点から考えると役立つ場合があります。
問題がメモ化に適しているかどうかを直感する方が通常は簡単です(手順は Slivvzの答え と同じですが、メンタルシフトは少し短いと思います)。ただし、メモ化によって問題を解決したら、再帰せずにメモキャッシュがどのように満たされているかを調べ、順番に満たすことができます。これにより、アルゴリズムが動的プログラミングアルゴリズムに変更されます。
TL; DR;バージョン:メモ化の観点から動的プログラミングを理解する方が簡単かもしれません。
動的プログラミングとは、本質的に次の2つです。
最適な部分構造
より大きなソリューションは、より小さなソリューションから派生できます。解決は双方向ではありません。
重複するサブ問題
小さなソリューションは何度も再利用されます。サブ問題がまったく重ならない場合、DP /メモ化のメリットはありません。あなたが持っているのは、代わりにdivide and conquerです。
DP問題への一般的なアプローチは次のとおりです。
機能する単純な再帰バージョンまたは反復バージョンを作成します。
関数が冗長な作業を行っていることに注意してください。
多くの場合、メモ化によって、その冗長な作業を回避する方法を見つけます。
私は単一の動的プログラミングソルバーを実装したことはありません-私の背景は、CSではなく、数学/物理/数値計算に適用されています-数年前に Project Euler 問題を始めたときまで。 DPで解決可能な問題があります(例 76 、 158 、 161 、 242 ですが、他にもたくさんあります)私の好きな種類であることが判明しました。役に立つテクニックになると、スポッティングは間違いなく上手くなります。基本的に、必要な経路の爆発を抑えることも可能な、ある種の再帰的な分割統治アプローチによって解決できると思われるものを探します。繰り返し発生する副問題を認識し、以前に計算された結果を再利用することによって調査されます。覚えておくべき最小限の状態ベクトルを特定できること、および無関係な「履歴」を消去できるかどうかは、重要なステップです。