web-dev-qa-db-ja.com

どのようにして問題を動的プログラミングに適していると特定しますか?

最近、動的プログラミングについて読んでいます。ゼロから始めて、現在DPの問題を特定して解決することに長けている人からの連絡を希望します。私はこれらの問題をDPとして特定し、簡潔な解決策を組み立てるのに苦労しています。

私は初心者向けDPの問題とMITリソースなど)のほとんどを経験しました

19
user110036

私は物理学の出身なので、たくさんの数学を学んでいます。 帰納法による証明との類似点を見つけることにより、再帰的/動的プログラミングソリューションに適した問題を簡単に見つけることができます。

帰納法による証明では、2つの部分があります。

  • あなたは何かが反復Nに当てはまる場合、それは反復N + 1にも当てはまることを証明します
  • あなたはそれが反復に当てはまることを証明します1

再帰的プログラミング/動的プログラミングでは:

  • 終了条件を特定します(たとえば、反復1のソリューションを配線します)
  • 反復N-1の解が与えられた場合、反復Nの解を計算します

したがって、他の人が答えたように、それは経験とヒントの選択の問題ですが、他のスキルを再利用してガイドすることができます。その後、私が述べた2つの部分を常に持つ必要があります。そうしないと、機能しません。

たとえば、セットのすべての順列を生成するには:

  • 終了条件:要素が1つしかない場合は、それを返します
  • 再帰:N個のアイテムの組み合わせの順列は、各要素を選択し、要素を削除することによって取得したサブセットのN-1セットの(多くの)順列のすべてと組み合わせることによって得られるNセットの順列です。
17
Sklivvz

ほとんどの動的プログラミング問題は、メモ化によって解決できます。メモ化は通常、より直感的でコーディングが簡単です。 DPの代わりにメモ化の観点から考えると役立つ場合があります。

問題がメモ化に適しているかどうかを直感する方が通常は簡単です(手順は Slivvzの答え と同じですが、メンタルシフトは少し短いと思います)。ただし、メモ化によって問題を解決したら、再帰せずにメモキャッシュがどのように満たされているかを調べ、順番に満たすことができます。これにより、アルゴリズムが動的プログラミングアルゴリズムに変更されます。

TL; DR;バージョン:メモ化の観点から動的プログラミングを理解する方が簡単かもしれません。

StackOverflow:動的プログラミングとメモ化:ボトムアップとトップダウンのアプローチ も参照してください。

8
Brian

動的プログラミングとは、本質的に次の2つです。

  1. 最適な部分構造
    より大きなソリューションは、より小さなソリューションから派生できます。解決は双方向ではありません。

  2. 重複するサブ問題
    小さなソリューションは何度も再利用されます。サブ問題がまったく重ならない場合、DP /メモ化のメリットはありません。あなたが持っているのは、代わりにdivide and conquerです。

DP問題への一般的なアプローチは次のとおりです。

  • 機能する単純な再帰バージョンまたは反復バージョンを作成します。

  • 関数が冗長な作業を行っていることに注意してください。

  • 多くの場合、メモ化によって、その冗長な作業を回避する方法を見つけます。

4
Jon Purdy

私は単一の動的プログラミングソルバーを実装したことはありません-私の背景は、CSではなく、数学/物理/数値計算に適用されています-数年前に Project Euler 問題を始めたときまで。 DPで解決可能な問題があります(例 76158161242 ですが、他にもたくさんあります)私の好きな種類であることが判明しました。役に立つテクニックになると、スポッティングは間違いなく上手くなります。基本的に、必要な経路の爆発を抑えることも可能な、ある種の再帰的な分割統治アプローチによって解決できると思われるものを探します。繰り返し発生する副問題を認識し、以前に計算された結果を再利用することによって調査されます。覚えておくべき最小限の状態ベクトルを特定できること、および無関係な「履歴」を消去できるかどうかは、重要なステップです。

2
timday