1. 程式人生 > >經典模型的狀態轉移方程

經典模型的狀態轉移方程

狀態轉移方程

動態規劃中當前的狀態往往依賴於前一階段的狀態和前一階段的決策結果。例如我們知道了第i個階段的狀態Si以及決策Ui,那麼第i+1階段的狀態Si+1也就確定了。所以解決動態規劃問題的關鍵就是確定狀態轉移方程,一旦狀態轉移方程確定了,那麼我們就可以根據方程式進行編碼。

在前面的文章《動態規劃-開篇》講到了如何設計一個動態規劃演算法,有以下四個步驟:

1、刻畫一個最優解的結構特徵。

2、遞迴地定義最優解的值。

3、計算最優解的值,通常採用自底向上的方法。

4、利用計算出的資訊構造一個最優解。

對於確定狀態轉移方程就在第一步和第二步中,首先要確定問題的決策物件,接著對決策物件劃分階段並確定各個階段的狀態變數,最後建立各階段的狀態變數的轉移方程。

例如用dp[i]表示以序列中第i個數字結尾的最長遞增子序列長度和最長公共子序列中用dp[i][j]表示的兩個字串中前 i、 j 個字元的最長公共子序列,我們就是通過對這兩個數字量的不斷求解最終得到答案的。這個數字量就被我們稱為狀態。狀態是描述問題當前狀況的一個數字量。首先,它是數字的,是可以被抽象出來儲存在記憶體中的。其次,它可以完全的表示一個狀態的特徵,而不需要其他任何的輔助資訊。最後,也是狀態最重要的特點,狀態間的轉移完全依賴於各個狀態本身,如最長遞增子序列中,dp[x]的值由 dp[i](i < x)的值確定。若我們在分析動態規劃問題的時候能夠找到這樣一個符合以上所有條件的狀態,那麼多半這個問題是可以被正確解出的。所以說,解動態規劃問題的關鍵,就是尋找一個好的狀態。

總結

下面對這幾天的學習總結一下,將我遇到的各種模型的狀態轉移方程彙總如下:

1、最長公共子串

假設兩個字串為str1和str2,它們的長度分別為n和m。d[i][j]表示str1中前i個字元與str2中前j個字元分別組成的兩個字首字串的最長公共長度。這樣就把長度為n的str1和長度為m的str2劃分成長度為i和長度為j的子問題進行求解。狀態轉移方程如下:

  1. dp[0][j] = 0; (0<=j<=m)
  2. dp[i][0] = 0; (0<=i<=n)
  3. dp[i][j] = dp[i-1][j-1] +1; (str1[i] == str2[j])
  4. dp[i][j] = 0; (str1[i] != str2[j])

因為最長公共子串要求必須在原串中是連續的,所以一但某處出現不匹配的情況,此處的值就重置為0。

2、最長公共子序列

區分一下,最長公共子序列不同於最長公共子串,序列是保持子序列字串的下標在str1和str2中的下標順序是遞增的,該字串在原串中並不一定是連續的。同樣的我們可以假設dp[i][j]表示為字串str1的前i個字元和字串str2的前j個字元的最長公共子序列的長度。狀態轉移方程如下:

  1. dp[0][j] = 0; (0<=j<=m)
  2. dp[i][0] = 0; (0<=i<=n)
  3. dp[i][j] = dp[i-1][j-1] +1; (str1[i-1] == str2[j-1])
  4. dp[i][j] = max{dp[i][j-1],dp[i-1][j]}; (str1[i-1] != str2[j-1])

3、最長遞增子序列(最長遞減子序列)

因為兩者的思路都是一樣的,所以只給出最長遞增子序列的狀態轉移方程。假設有序列{a1,a2,...,an},我們求其最長遞增子序列長度。按照遞推求解的思想,我們用F[i]代表若遞增子序列以ai結束時它的最長長度。當 i 較小,我們容易直接得出其值,如 F[1] = 1。那麼,如何由已經求得的 F[i]值推得後面的值呢?假設,F[1]到F[x-1]的值都已經確定,注意到,以ax 結尾的遞增子序列,除了長度為1的情況,其它情況中,ax都是緊跟在一個由 ai(i < x)組成遞增子序列之後。要求以ax結尾的最長遞增子序列長度,我們依次比較 ax 與其之前所有的 ai(i < x), 若ai小於 ax,則說明ax可以跟在以ai結尾的遞增子序列之後,形成一個新的遞 增子序列。又因為以ai結尾的遞增子序列最長長度已經求得,那麼在這種情況下,由以 ai 結尾的最長遞增子序列再加上 ax 得到的新的序列,其長度也可以確定,取所有這些長度的最大值,我們即能得到 F[x]的值。特殊的,當沒有ai(i < x)小 於ax, 那麼以 ax 結尾的遞增子序列最長長度為1。 即F[x] = max{1,F[i]+1|ai<ax && i<x}。

 4、最大子序列和的問題

假設有序列{a1,a2,...,an},求子序列的和最大問題,我們用dp[i]表示以ai結尾的子序列的最大和。

dp[1] = a1; (a1>=0 && i == 1)

dp[i] = dp[i-1]+ai; (ai>=0 && i>=2)

dp[i] = 0; (dp[i-1] + ai <=0 && i>=2)

 5、數塔問題(動態搜尋)

給定一個數組data[n][m]構成一個數塔求從最上面走到最低端經過的路徑和最大。可以假設dp[i][j]表示走到第i行第j列位置處的最大值,那麼可以推出狀態轉移方程:

dp[i][j] = max{dp[i-1][j-1],dp[i-1][j]} + data[i][j];

for(i=n-1;i>=1;i--){

     for(j=1;j<=i;j++){

         dp[i][j]=max{dp[i-1][j-1],dp[i-1][j]}+s[i][j]

     }

}
View Code

6、(01)揹包問題

這是一個經典的動態規劃問題,另外在貪心演算法裡也有揹包問題,至於二者的區別在此就不做介紹了。

假設有N件物品和一個容量為V的揹包。第i件物品的體積是v[i],價值是c[i],將哪些物品裝入揹包可使價值總和最大?

每一種物品都有兩種可能即放入揹包或者不放入揹包。可以用dp[i][j]表示第i件物品放入容量為j的揹包所得的最大價值,則狀態轉移方程可以推出如下:

dp[i][j]=max{dp[i-1][j-v[i]]+c[i],dp[i-1][j]};

  for (int i = 1;i <= N;i++) //列舉物品  
    {  
        for (int j = 0;j <= V;j++) //列舉揹包容量  
        {  
            f[i][j] = f[i - 1][j];  
            if (j >= v[i])  
            {  
                f[i][j] = Max(f[i - 1][j],f[i - 1][j - v[i]] + c[i]);  
            }  
        }  
    }  
View Code

7、矩陣連乘(矩陣鏈問題)-參考《演算法導論》

例如矩陣鏈<A1,A2,A3>,它們的維數分別為10*100,100*5,5*50,那麼如果順序相乘即((A1A2)A3),共需10*100*5 + 10*5*50 = 7500次乘法,如果按照(A1(A2A3))順序相乘,卻需做100*5*50 + 10*100*50 = 75000次乘法。兩者之間相差了10倍,所以說矩陣鏈的相乘順序也決定了計算量的大小。

我們用利用動態規劃的方式(dp[i][j]表示第i個矩陣至第j個矩陣這段的最優解,還有對於兩個矩陣A(i,j)*B(j,k)則需要i*j*k次乘法),推出狀態轉移方程:

dp[i][j] = 0; (i ==j,表示只有一個矩陣,計算次數為0)

dp[i][j] = min{dp[i][k] + dp[k+1][j] + p[i-1]*p[k]*p[j]}; (i<j && i<=k<j)

dp[1][n]即為最終求解.

#define MAXSIZE 100

int dp[MAXSIZE][MAXSIZE];//儲存最小的就算次數
int s[MAXSIZE][MAXSIZE];//儲存斷點,用在輸出上面

int i, j, tmp;

for (int l = 2; l <= n; l++){//j-i的長度,由於長度為1是相同的矩陣那麼為0不用計算
    for (i = 1; i <= n - l + 1; i++){//由於j-i =l - 1 , 那麼j的最大值為n,所以i上限為 n - l+1;
        j = i + l - 1;//由於j-i = l - 1 , 那麼j = l+i-1
        dp[i][j] = dp[i + 1][j] + r[i] * c[i] * c[j];//初始化,就是k = i;
        s[i][j] = i;
        for (k = i + 1; k < j; k++){//迴圈列舉k i < k < j
            tmp = dp[i][k] + dp[k + 1][j] + r[i] * c[k] * c[j];
            if (dp[i][j] > tmp){
                dp[i][j] = tmp;//更新為最小值
                s[i][j] = k;
            }
        }
    }
}

//遞迴呼叫輸出
void output(int i, int j){
    if (i == j){
        printf("A%d", i);//當兩個相等的時候就不用繼續遞迴就輸出A
        return;//返回上一層
    }

    else{
        printf("(");
        output(i, s[i][j]);
        printf(" x ");
        output(s[i][j] + 1, j);
        printf(")");
    }
}
View Code

ps

如有錯誤的地方或者本人理解錯的地方,請指出,共同進步!!!

相關推薦

經典模型狀態轉移方程

狀態轉移方程 動態規劃中當前的狀態往往依賴於前一階段的狀態和前一階段的決策結果。例如我們知道了第i個階段的狀態Si以及決策Ui,那麼第i+1階段的狀態Si+1也就確定了。所以解決動態規劃問題的關鍵就是確定狀態轉移方程,一旦狀態轉移方程確定了,那麼我們就可以根據方程式進行編碼。 在前面的文章《動態規劃-開篇

DP問題各種模型狀態轉移方程

1(最長公共子串(注意和最長公共子序列區別)) 兩個字串str1和str2,長度分別為(l1,l2) dp[i][j]表示以兩個字串分別以第i和第j個字元結尾所能達到的公共子序列的長度,由於下面涉及到i-1和j-1,那麼這個時候我們一般從i=1和j=1開始到

hdu 動態規劃(46道題目)傾情奉獻~ 【只提供思路與狀態轉移方程】(轉)

Robberies http://acm.hdu.edu.cn/showproblem.php?pid=2955     揹包;第一次做的時候把概率當做揹包(放大100000倍化為整數):在此範圍內最多能搶多少錢  最腦殘的是把總的概率以為是搶N家銀行的概率之和… 把狀

轉】HDU 動態規劃(46道題目)傾情奉獻~ 【只提供思路與狀態轉移方程

Robberies http://acm.hdu.edu.cn/showproblem.php?pid=2955 揹包;第一次做的時候把概率當做揹包(放大100000倍化為整數):在此範圍內最多能搶多少錢 最腦殘的是把總的概率以為是搶N家銀行的概率之和… 把狀態轉移方程寫

數字三角形問題 動態規劃問題 狀態轉移方程

數字三角形問題 Time Limit: 1000MS Memory Limit: 65536KB Submit Statistic Problem Description 給定一個由n行數

揹包問題與動態規劃狀態轉移方程1

阿福是一名經驗豐富的大盜。趁著月黑風高,阿福打算今晚洗劫一條街上的店鋪。這條街上一共有 N 家店鋪,每家店中都有一些現金。阿福事先調查得知,只有當他同時洗劫了兩家相鄰的店鋪時,街上的報警系統才會啟動,然後警察就會蜂擁而至。作為一向謹慎作案的大盜,阿福不願意冒著被警察追捕的風險

HDU 動態規劃(46道題目)傾情奉獻~ 【只提供思路與狀態轉移方程

移方程寫成了f[j]=max{f[j],f[j-q[i].v]+q[i].money}(f[j]表示在概率j之下能搶的大洋);          正確的方程是:f[j]=max(f[j],f[j-q[i].money]*q[i].v)  其中,f[j]表示搶j塊大洋的最大的逃脫概率,條件是 f[j-q[i]

C/C++用狀態轉移表聯合函數指針數組實現狀態機FSM

pre nsf div script addclass .text 特點 sed 二維 狀態機在project中使用很的頻繁,有例如以下常見的三種實現方法: 1. switch-case 實現。適合簡單的狀態機。 2. 二維狀態表state-even

【狀壓+狀態轉移】A Famous Airport Managere

div logs log first 第一個 cout init ring pan https://www.bnuoj.com/v3/problem_show.php?pid=25653 【題意】 給定一個3*3的九宮格,模擬一個停機坪。第一個格子一定是‘*‘,代表tak

行為型模型 狀態模式

簡化 turn 通過 include pla alt 場景 處的 ext 行為型模型 狀態模式 Context:用戶對象 擁有一個State類型的成員,以標識對象的當前狀態; State:接口或基類 封裝與Context的特定狀態

【BZOJ 3232】圈地遊戲 二分+SPFA判環/最小割經典模型

detail blank 簡單 tails double 就是 inline ref 如果 最小割經典模型指的是“一堆元素進行選取,對於某個元素的取舍有代價或價值,對於某些對元素,選取後會有額外代價或價值”的經典最小割模型,建立倒三角進行最小割。這個

POJ 3280 Cheapest Palindrome ( 區間DP && 經典模型 )

ide aps class nbsp 圖片 pri 子串 microsoft using 題意 : 給出一個由 n 中字母組成的長度為 m 的串,給出 n 種字母添加和刪除花費的代價,求讓給出的串變成回文串的代價。 分析 : 原始模型 ==> 題意和本題差不多,

Bomb HDU 3555 dp狀態轉移

for true 表數 init long cout bool AC 基礎 題目:http://acm.hdu.edu.cn/showproblem.php?pid=3555 題意: 給出一個正整數N,求出1~N中含有數字“49”的數的個數 思路: 采用數位dp的狀態轉

線程各種狀態轉移分析

java thread 線程分析 線程在它的生命周期中會處於各種不同的狀態:新建、等待、就緒、運行、阻塞、死亡。1、新建用new語句創建的線程對象處於新建狀態,此時它和其他java對象一樣,僅被分配了內存。2、等待當線程在new之後,並且在調用start方法前,線程處於等待狀態。 3、就緒當一個線

【神經網絡篇】--基於數據集cifa10的經典模型實例

cas 環境 常用 及其 分享 執行 獨立 -- 解壓 一、前述 本文分享一篇基於數據集cifa10的經典模型架構和代碼。 二、代碼 import tensorflow as tf import numpy as np import math import time fr

【Keras篇】---利用keras改寫VGG16經典模型在手寫數字識別體中的應用

model類 都是 ast 訓練樣本 轉化 一個 h5py 次梯度 窗口 一、前述 VGG16是由16層神經網絡構成的經典模型,包括多層卷積,多層全連接層,一般我們改寫的時候卷積層基本不動,全連接層從後面幾層依次向前改寫,因為先改參數較小的。 二、具體 1、因為本文中代碼需

Deck of Cards ZOJ - 2852 dp 多決策 狀態轉移

string 表示 nbsp math line begin zju sign nal 題意:一個特殊21點遊戲 具體http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2852 題解:建一個三維dp,表

POJ1644狀態轉移的思想——排列組合

是不是 div out ios 就會 影響 mes ring stream m個物品放n個盒子,盒子物品都相同,問你放的方法總數是多少 看著像個排列組合,算著算著就發現我排列組合都忘得差不多啦,哎,什麽時候能打敗遺忘呢 然後想用dp做,但是轉移的方面沒有想好 看了看題解感覺

2018南京網路賽 L Magical Girl Haze(最短路、堆、狀態轉移

我們設定dis[i][k]表示走到第i號點,免費經過了k條邊的最短路。  對於我們當前找到的終點,嘗試起點的狀態去更新,不選擇此條邊免費的狀態和選擇此條邊免費的狀態,再將這兩個狀態壓入佇列去更新可以到達的其他狀態。 #include<cstdio> #include&l

深度學習目標檢測經典模型比較(RCNN、Fast RCNN、Faster RCNN)

深度學習目標檢測經典模型比較(RCNN、Fast RCNN、Faster RCNN)   Faster rcnn是用來解決計算機視覺(CV)領域中目標檢測(Object Detection)的問題的。 區別目標分類、定位、檢測 一、傳統的目標檢測方法 其實目標檢