EDITORIAL言葉:
実際には、冬季オリンピックの合宿時の最後の年に、それはDPと接触していたが、彼は自分の時間に、実際には非常に静かです、そして、把握することはできませんではないだろう、問題には覚えていないことができ、また、それを徹底的に理解することは確実であると考えられます - - しかし、合計はまだ来てほしいです。
だから今DPの楽しみはそれを再生します。
DPカテゴリ:
まず、簡単な基礎DP
このようなメイン州のDPの一部です簡単に比較が本当に方程式を転送したい、基本的な問題は、むしろ一般的であると述べました。含む再帰的な、バックパック、LIS(最長増加するシーケンス)、LCS(最長共通シーケンス)
第二に、間隔DP
第三に、木のDP
第四に、デジタルDP
第五に、圧縮DPの状態
まあ、柔らかい柿のピンチで始まります
Dpが最初にそれの基本的な考え方を理解します。
活動の全体のプロセスは、最良の結果を達成するように、現実の生活では、いくつかのプロセスは、いくつかの相互に関係の段階に分けることができ、その決定の各段階は、なされなければなりません。その中で、意思決定のすべての段階が現在直面状態の両方に依存する選択するだけでなく、将来の発展に影響を与え、決定が決定され、各ステージの後、意思決定のシーケンスを構成しています。
動的なプログラミングの問題を満たす三つの重要な性質
- 最適な基礎構造プロパティ:問題への次善の解決の問題の解決にも最高に含まれている場合、我々は問題は構造的な次善を持っていると言うこと(すなわち、最適化の原則を満たしています)。問題解決の動的プログラミングアルゴリズムのサブ最適な構造特性は重要な手がかりを提供します。
- 自然は部分問題の重複:重複問題を常にいくつかのサブ問題は、計算を複数回繰り返されるたびに生成されたトップダウンの問題解決に関して、新たな問題の部分問題の再帰的なアルゴリズムを、ないプロトンを指します。動的プログラミングアルゴリズムは、一度だけ、各副問題の計算、このサブ問題の重なり合う性質を利用し、その後、あなたは、サブ問題がちょうどテーブルで、再計算された計算する必要がある場合、テーブルに結果を保存します単純に高い効率が得られるように、結果を見てください。
- いいえ後効果:特定の順序に従って並んだ様々な段階の後、状態の所与の段階のために、各段階の以前の状態が直接のみ、この現在の状態を経て、将来の決定に影響を与えることができません。言い換えれば、各状態は、過去の歴史の完全な要約です。これは何の後方向、またノー後の効果として知られていません。
デジタルピラミッド - OK、今、あなたはそれの最初の単純なモデルを見始めます。
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
一般的な考え方:
方法1:外挿シス
起動パスを決定し、中間点と終了点の相対的な不確実性は、F [X] [Y](1,1)発着(X、Y)からのものであり、最大のパスの重みを定義します。
最大値の末尾に加える(X、Y)ので、それは(1,1)である必要があるのみで2つのパスの(x、y)の最大値、および(x、y)に到達するまで、上部左、Aゼロのその左上または右上の値は、状態遷移方程式がまだ有効であるので、右、当然のことながら、ポイントの両側には、ない心配を行います。
F [X] [Y] =最大{F [I-1] [Y-1]、F [I-1] [Y]} + [X] [Y]。
最後に、[1〜n]の最大値[n]はFでありANS
方法2:逆推論(新規な脳回路)
トップダウン、ボトムアップ計算による分析。
F [X] [Y] =最大{F [X + 1] [Y + 1] + F [X + 1] [Y]} + [X] [Y]。
(I ++; I <= N I = 1の整数)のために
F [n]は[I] = [N] [i]は、
その後
LIS(立ち上がり最長シーケンス)
#include <iostreamの> する#include <cstdioを> する#include <アルゴリズム> の#define MAX 110000 使用して 名前空間STDを、 int型[MAX]を、F [MAX]。 int型のmain() { int型、nは cinを >> N; 以下のために(INT iが= 1 ; I <= N; I ++ ) CIN >> [I]。 用(INT iは= 1 ; I <= N I ++ ) { F [I] = 1 。 以下のための(int型 J = 1; J <= N- 1、J ++ ) 場合([I]> [J])F [I] = MAX(F [J] + 1 、F [I])。 } ソート(F + 1、F + 1 + N)。 COUT << F [N]。 リターン 0 ; }
上記0(N ^ 2)であります
私自身の理解:
F [i]は配列の最長の長さの終わりに[I]で表さ配列は依然としてSO Fに初期化最短オン(自体)を有し、[I] = 1。
より多くの[i]は小さな、例えば、レッツ・セット[k]の背後にあるよりも、それがあれば、我々は選択することができますし、この時点で[K]の後ろに接続されているの文字列の末尾の[i]が、その数になります[k]は、シーケンス長さの端をf [i]が+1です。
我々は値比較を与える[i]をフロントに接続されて知られているF [i]と選択値にしたいので、もちろん、これは、[i]は、必ずしも最長の背面に接続されていないを選択し、
即F [I] = MAX(F [J] + 1 、F [I])。
順次通過する[1]〜[n]は、その後、LISを求めることができるどのような種類。
、そこ0(nlongn)の文言がありますが、まあ、私はああではないでしょう。。。
LCS(最長共通部分列):
1 // T:最长公共子序列
2の#include <cstdioを>
3の#include <アルゴリズム>
4
5 の#define MAXN 2111年
6
7 使って 名前空間STDを、
8
9 int型N、M。
10 INT [MAXN]、B [MAXN]。
11 INT F [MAXN] [MAXN]。
12 INT メイン(){
13 のscanf(" %D%D "、&N、&M)。
14 のために(INT iは= 1 ; iが<= N; I ++)のscanf(" %dの"、&[I])。
15 のために(INT iは= 1のscanf(; I <= M Iは++)" は%d "、&B [I])。
16
17 のために(INTは iは= 1、I ++; <I = N ){
18 のための(int型 J = 1 ; J <= Mであり、j ++ ){
19
20 F [I] [J] = MAX(F [I - 1 ] [J]、F [i]は[J - 1 ])。
21
22 であれば([I] == B [J])F [I] [J] = MAX(F [I] [J]、F [I - 1 ] [J - 1 ] + 1);
23
24 他 F [I] [J] = MAX(F [I] [J]、F [I - 1 ] [J - 1 ])。
25
26 }
27 }
28 のprintf(" %D \ n " 、F [n]は[M])。
29 リターン 0 ;
30 }
OK、今、私たちは、トピックのいくつかを見て:(続)