[アルゴリズムノート]動的計画法DP、アルゴリズムの説明

【アルゴリズムノート】動的計画法DP

動的計画法

誰もがコードの実装で再帰を広く使用していると思いますが、実装は非常に単純ですが、純粋な再帰ですが、アルゴリズムではほとんどの場合両方を持つことはできません。再帰はそれ自体への関数呼び出しであり、現時点では、時間とスペースの観点から、すべての関数呼び出しがメモリスタックに割り当てられ、一時変数を保存し、パラメータを保存し、アドレスを返します。さらに、再帰では計算手順が繰り返されることがよくあります。最後に、呼び出しが多すぎると簡単にオーバーフローする可能性があります。

動的計画法は、繰り返し呼び出しの問題を大幅に解決します。分割統治法(分割統治法)とは、動的計画法のサブ問題が完全に重複していないという点で大きく異なります。実際、動的計画法とトラバーサルアルゴリズムは非常に似ています。 。??のアイデアに優れたものは何もありませんが、実行された保存された計算については、繰り返し呼び出したときに結果をすばやく計算でき、時間を節約できます。欲張りアルゴリズムを使用して解決できるすべての問題は、動的計画法によって解決できることは言及する価値があります。最短経路Floyd-Warshallアルゴリズム(Floyd-Warshallアルゴリズム)など、多くの特定のアルゴリズムには動的計画法の影があります。

定義:

問題を分割することによって問題の状態と状態の間の関係を定義するアルゴリズム。これにより、問題を再帰的に(または分割統治)方法で解決できます[1]。

もちろん、この定義は最適ではありません。繰り返し発生するサブ問題を、重複するサブ問題(重複するサブ問題)と呼びます。その場合、その定義は次のようになります。問題をいくつかの重複するサブ問題に分割し、小さな問題の解決策を組み合わせて、大きな問題の解決策を取得します。

動的計画法は、計算科学(AI、グラフィックスなど)、情報理論、サイバネティックスなどの分野で広く使用されています。

ステップ

動的計画法は通常、最適化問題を解決するために使用されます。この種の問題には多くの実行可能な解決策があり、それぞれの解決策には価値があります。最適な値(最大値または最適値)を持つ解決策を見つけたいと考えています。
最適値に達する複数の解が存在する可能性があるため、このような解を問題の最適解最適解)と呼びます。最適解(最適解)ではありません[2. Thomas H. Cormen、Charles E. Leiserson 、Ronald L. Rivest and Clifford Stein、2019.6、China Machine Press、204]

1.最適解の構造特性を特徴付けます
2.最適解の値
再帰的に定義します3.最適解の値を計算します
4.計算された情報を使用して最適解を構築し
ます最初の3つのステップは動的プログラミングの基礎です問題を解決するために、解自体ではなく最適解の値のみが必要な場合は、4番目のステップを無視できます。

1.フィボナッチ数列
次のコードを確認します

double F(int n){
	return (n<=1)?1:F(n-1)+F(n-2)
}

ランタイムを

図1に示します。

計算T(N)= O(2 ^ n)の
我々は計算する必要がある場合はF(44) 我々は計算する必要がF(43)F(42) および計算するF(43)我々は計算する必要があり(Fを42)、関数内の数が少なくなると、状況は制御不能になります。
ここに画像の説明を挿入します
図2

もちろん、* F(10)*を約1,000万回計算する必要はないので、この問題を解決する必要
があります。次のような実行可能な戦略があります。
・二重計算を回避するために、中間計算の量をに格納します。テーブル(記憶)
・私たちは覚えていますこれらの計算の値は次に可能な繰り返し呼び出しです
最適な問題を解決するための動的計画法のプロセスでは、トップダウンソリューションは同じものの最適なソリューションを繰り返し取得する必要があるかもしれませんサブ問題。これは、分割統治アルゴリズムのサブ問題が完全に異なるため、分割統治アルゴリズムとは大幅に異なる点でもあり、効果が向上します。

#define MAX 100
int d[MAX]
int F(int n){
    
    
	if(n<=2)
	{
    
    
		return 1;
	}
	else
	{
    
    
		d[n-1]=F(n-1);
		d[n-2]=F(n-2);
		d[n]=d[n-1]+d[n-2];
		return d[n]
	}
}
//也可以用循环的方式
}

2.インターバルスケジューリング
・コースjはs [j]で始まり、f [j]で終わり、重要度はw [j]> 0です。
・2つのコースが重ならない場合、これら2つのコースは互換性があります。 。
目標:最も重要な互換性のあるコースのセットを見つけます。
ここに画像の説明を挿入します
図3

浅いところから深いところへと進みますが、最も力ずくの方法(力ずく)は、もちろん、各コースのすべての配置を取り出して、どの重量が最大かを確認することです。ただし、これには明らかに改善の余地があります。たとえば、これらのコースの配置には多くの重複が必要です。じゃあ何をすればいいの?
重みがすべて1の場合、欲張りアルゴリズムを使用して、終了時間に従って直接並べ替え、後ろから開始できます。ただし、ここでは異なる重みが追加されるため、含まれるコースが多いほど、必ずしも最終的な重みと最大値が得られるとは限りません。
この場合、DPが役立ちます。考え方は上記の方法と似ていますが、配列です。 pを追加する必要があります。アシスト

p [j] = jよりも小さいコースjと互換性のある最大のコース
。次の図では、p [2] = 0、p [7] = 3
ここに画像の説明を挿入します
図4

我々はより完全にそれを提示
デフ。OPT(J)=最大重量和とコースのいずれかの互換性のあるサブセットを含有する唯一のコース1、2、...、Jの
ゴール。OPT(N)=最大の重み和相互互換性を持ちますコースセット
ケース1.OPT(j)にはコースjが含まれていません
。したがって、その解決策は、コース1、2、...、jの最大重みのみを含み、相互に互換性があることです。

ケース2.OPT(j)にコースjが含まれている
・重みを追加するw [j]
・互換性のないコースが含まれていない{p [j] + 1、…、j-1}
・1、2、...、p( j)最適なソリューション

上記の分析の後、それは非常に明確ですか?動的計画法のベルマン公式も出てきました
ここに画像の説明を挿入します
図5

アルゴリズムの複雑さ(複雑さ)を分析してみましょう。
各反復で最悪はOPT(j-1)であるため、動的計画法プロセスでは、最大2n回、つまりO(n)、およびp [jで実行されることに注意してください]取得は、提供されたコース間隔を終了時間に従ってソートし、後ろから前に数えることによって取得されます。合計の複雑さはO(nlogn)であり、合計のアルゴリズムの複雑さはO(nlogn)です。

3.マルチポイントカーブフィッティング
もっと面白いと思う別の例を挙げましょう。私たちの研究プロセスの一部であるデータ処理を行うときは、誰もがカーブフィッティングを使用すると思いますが、表示されるポイントが異なる場合間隔が大きく変化するため、曲線をあてはめする方法はありません。以下では、動的プログラミングを使用してこの問題を解決します。
まず、最も基本的な問題を見てみましょう


与えられた平面内の最小二乗n点(x1、y1)、(x2、y2)、...、(xn、yn)。フィットする線y = ax + bを見つけます。
最も一般的な問題は、最小二乗法を使用することです。
ここに画像の説明を挿入します
図6
!](https://img-blog.csdnimg.cn/20210110134349420.png)

図7

セグメント化された最小二乗
・n点(x1、y1)、…、(xn、yn)、x1 <x2 <…<xnが与えられた場合、f(x)の誤差を最小化する曲線のセットを見つけます
ここに画像の説明を挿入します
図8
f(x)= E + cL
E:各直線の二乗誤差の合計
L:直線の数
OPT(j)=点p1、…、pjの最小消費量
eij = pi、…、pjのSSE
、毎回Cost = eij + c + OPT(i-1)は
最終的にベルマンの方程式を取得し
ここに画像の説明を挿入します
ます図9

サンプル

すべてのアルゴリズムには、次の3つのコンポーネントが必要です。主なアイデア、正当性の証明、および実行時分析

1.アルゴリズムの主なアイデア。このセクションでは、アルゴリズムのアイデアを正しく伝える必要があります。ソリューションのすべての詳細や正しい理由を提供する必要はありません。たとえば、動的計画問題では、この部分のサブ問題、基本条件、および再帰式を教えてください。擬似コードを使用して、見栄えを良くすることもできます

2.アルゴリズムの正しさの証明。入力が何であれ、アルゴリズムが正しいことを証明する必要があります。ループと反復アルゴリズムの場合、通常の方法は不変条件を探すことです。ループ不変条件は、次の3つの原則に従う必要があります
。1)最初の反復とループの直前である
2)i番目の反復の直前である場合は、i +1回目の直前でもある必要がありますはい
3 )最後の反復またはループの後で
正しい場合、出力は証明として正しいです。この不変条件は、システムによって注意深く記述される必要があります。クラスで正しいことが証明された場合、次のようにはなりません。毎回その正しさを証明する

3. O(・)でマークされた複雑さ分析、通常は時間計算量分析。そして、なぜこの複雑さを証明する

たくさん言ったので、例を挙げましょう。この例は私の宿題からのものです。
長さNと値Wの非負の整数のセットが与えられた場合、この数値のセットにサブセットがあるかどうかを判断します。サブセットの数はW?
1に等しい。コアアイデア:Sがこの入力非負整数のセットを表すとすると、動的プログラミングを実現するためにブール型の2次元配列dp [] []を構築します。dp[i] [j ]は、Sを含める前にiがあるかどうかを示します。要素のサブセットとサブセットの合計がjである場合、dp [N-1] [W]を知りたいです。最初に初期化します。j= 0の場合、dp [i] [j] = true、ベルマンの式は
ここに画像の説明を挿入します
図10です

2.正しさ
明らかに、空のセットはすべてのセットのサブセットであるため、j = 0の場合、dp [i] [j] = trueです。dp [i] [j]の場合、i番目の要素がjより大きい場合、このサブセットは最終的な回答に存在しません(dp [i] [j] = dp [i-1] [j])。それ以外の場合は2つのケースがあります。回答にi番目の要素が含まれていない場合、dp [i] [j] = dp [i-1] [j]です。回答にi番目の要素が含まれている場合、サブセットとリデュース、dp [i] [j] = dp [i-1] [jS [i]]。上記の2つの条件d [i] [j]のいずれかを満たすことは正しいです。

3.複雑さの分析
ループには2つの層があり、1つはセットの長さで、もう1つは値Wであるため、複雑さはθ(NW)です。

ああ、宿題を翻訳するのにうんざりしているので、みんなに私の答えを見せましょう。
ここに画像の説明を挿入します
図11

総括する

一般に、動的計画法の考え方は非常に単純です。つまり、以前に計算された値を保存することで、繰り返し計算する時間を節約できます。3つのステップに分けられ、サブ質問を定義し、メイン質問をサブ質問に分割し、小さなサブ質問への回答がより大きなサブ質問への回答を構成できるようにすることができる小さなサブ質問から大きなサブ質問の順序を決定します。質問。分析方法も非常にシンプルで、2つのうちの1つを選択し、もう1つを選択し、新しいパラメーターblablablaを追加します(満足のいくブログを書くのに6時間近くかかりました。想像もしていませんでした。休日でなければ)

おすすめ

転載: blog.csdn.net/Cplus_ruler/article/details/112414247