1. 程式人生 > >動態規劃從入門到精通(一)-入門篇

動態規劃從入門到精通(一)-入門篇

大三的春招,由於自己的不足,過得十分艱難。在各大公司的筆試題中,動態規劃是一個必考點。突然冒出一個想法,寫一個“動態規劃從入門到精通”系列,與各大網友一起交流學習。

學習動態規劃,愚認為,就是解決以下的三個問題:
什麼是動態規劃?什麼時候要用動態規劃?怎麼使用動態規劃?

讓我們一個一個來解決!

1、什麼是動態規劃?
這裡參考百度百科,動態規劃是求解決策過程最優化的數學方法。把多階段過程轉化為一系列單階段問題,利用各階段之間的關係,逐個求解,創立了解決這類過程優化問題的新方法——動態規劃。

2、什麼時候要用動態規劃?
如果要求一個問題的最優解(通常是最大值或者最小值),而且該問題能夠分解成若干個子問題,並且小問題之間也存在重疊的子問題

,則考慮採用動態規劃。

3、怎麼使用動態規劃?
我把下面稱為動態規劃五部曲:
1. 判題題意是否為找出一個問題的最優解
2. 從上往下分析問題,大問題可以分解為子問題,子問題中還有更小的子問題
3. 從下往上分析問題 ,找出這些問題之間的關聯(狀態轉移方程)
4. 討論底層的邊界問題
5. 解決問題(通常使用陣列進行迭代求出最優解)



紙上得來終覺淺,絕知此事要躬行。舉幾個例子:
例子1:
劍指Offer(第二版)面試題14:剪繩子
給你一根長度為n的繩子,請把繩子剪成m段 (m和n都是整數,n>1並且m>1)每段繩子的長度記為k[0],k[1],…,k[m].請問k[0]k[1]

…*k[m]可能的最大乘積是多少?

例如,當繩子的長度為8時,我們把它剪成長度分別為2,3,3的三段,此時得到的最大乘積是18.
看完題目,我們按照上面提到的“動態規劃五部”解決問題
1、判題題意是否為找出一個問題的最優解
看到字眼是“可能的最大乘積是多少”,判斷是求最優解問題,可以用動態規劃解決;

2、從上往下分析問題,大問題可以分解為子問題,子問題中還有更小的子問題
題目中舉了個例子:當繩子的長度為8時,我們把它剪成長度分別為2,3,3的三段,此時得到的最大乘積是18;我們可以從這裡開始突破,把長度為8繩子的最大乘積分解為數個子問題,長度為8我們可以把它看成長度為1和7的繩子的和,或者長度 為2和6的繩子的和,或者長度為3和5的繩子的和and so on!
到這裡,相信大家已經看到一絲真理了吧?

3. 從下往上分析問題 ,找出這些問題之間的關聯(狀態轉移方程)
在第二點時,我們已經從上到下分析問題了,現在我們要從下往上分析問題了。分析可知,
f(8) 的值就是f(1)*f(7),f(2)*f(6),f(3)*f(5),f(4)*f(4)它們之中的最小值,即f(8) = Max{f(1)*f(7),f(2)*f(6),f(3)*f(5),f(4)*f(4)}
只要知道f(1)到f(7)的值就能求出f(8);對於f(7),只要知道f(1)到f(6)的值就能求出f(6);對於f(6),只要知道f(1)到f(5)的值就能求出f(6);以些類推,我們只要知道前幾個邊界的值,就能一步步迭代出後續的結果!
狀態轉移方程: f(n)=Max{f(n-i)*f(i)} i={1,2,3,…,n/2}

4. 討論底層的邊界問題
底層的邊界問題說的就是最小的前幾個數值的f(n)的值,本題中就是f(0)、f(1)、f(2)、f(3)的值
對於f(0),長度為0的繩子,沒辦法剪,沒有意義
對於f(1),長度為1的繩子,沒辦法剪,設為1
對於f(2),長度為2的繩子,只有一種剪法,剪成兩段長度為1的繩子,但剪後的乘積為1,比自身更小;如果不是求自身的值,要求乘積最大值的話就沒必要剪。
對於f(3),長度為3的繩子,只有一種剪法,剪成兩段長度為1和2的繩子,但剪後的乘積為2,比自身更小;如果不是求自身的值,要求乘積最大值的話也沒必要剪。

5、解決問題
這一部就是寫程式碼了

public static int cutting(int n) {
        //長度小於等等於1沒辦法剪
        if(n <= 1)
            return 0;
        //對於f(2),長度為2的繩子,只有一種剪法,剪成兩段長度為1的繩子,剪後的乘積為1
        if(n == 2)
            return 1;
        //對於f(3),長度為3的繩子,只有一種剪法,剪成兩段長度為1和2的繩子,但剪後的乘積為2
        if(n == 3)
            return 2;
        int max = 0;
        //陣列用於儲存繩子乘積最大值
        int value[] = new int[n + 1];
        value[0] = 0;
        value[1] = 1;
        //剪後的乘積為1,比自身更小;如果不是求自身的值,要求乘積最大值的話就沒必要剪
        value[2] = 2;
        //剪後的乘積為2,比自身更小;如果不是求自身的值,要求乘積最大值的話也沒必要剪
        value[3] = 3;
        //從f(4)開始迭代
        for(int i = 4;i <= n; i++) {
            max = 0;
            for(int j = 1;j <= i/2; j++) {
                int val = value[j] * value[i - j];
                max = val > max ? val : max;
            }
            value[i] = max;
        }
        max = value[n];
        return max;
}

對於剛學習動態規劃的同學,看完上面那題會有點吃力吧?那我們再來一題簡單的,給大家增加信心!

例子2:
跳臺階問題
一隻青蛙一次可以跳上1級臺階,也可以跳上2級臺階。求該青蛙跳上一個n級臺階總共有多少種跳法。

1、判題題意是否為找出一個問題的最優解
這個我還真的看不出,直覺判斷這題可以通過動態規劃迭代出來….有經驗的網友可以分享下看法,指導一下本小白白。

2、從上往下分析問題,大問題可以分解為子問題,子問題中還有更小的子問題
題目中沒有給粟子,我們可以自己舉點粟子。例如,跳上一個6級臺階臺階,有多少種跳法;由於青蛙一次可以跳兩階,也可以跳一階,所以我們可以分成兩個情況
1、青蛙最後一次跳了兩階,問題變成了“跳上一個4級臺階臺階,有多少種跳法”
2、青蛙最後一次跳了一階,問題變成了“跳上一個5級臺階臺階,有多少種跳法”
由上可得f(6) = f(5) + f(4);
由此類推,f(4)=f(3) +f(2)

3.、從下往上分析問題 ,找出這些問題之間的關聯(狀態轉移方程)
跟上面的例題一相同,可以由f(1)逐漸迭代上去
由2可得,狀態轉移方程為:f(n)=f(n-1)+f(n-2)

4、邊界情況分析
跳一階時,只有一種跳法,所以f(1)=1
跳兩階時,有兩種跳法,直接跳2階,兩次每次跳1階,所以f(2)=2
跳兩階以上可以分解成上面的情況

5、解決問題

public static int jump(int n) {
        //無意義的情況
        if(n <= 0)
            return 0;
        if(n == 1)
            return 1;
        if(n == 2)
            return 2;
        //陣列用於儲存跳n階的跳法數
        int[] value = new int[n + 1];
        value[0] = 0;
        value[1] = 1;
        value[2] = 2;
        for(int i = 3; i <= n; i++) {
            value[i] = value[i - 1] + value[i - 2];
        }
        return value[n];
}

相關推薦

動態規劃入門精通-入門

大三的春招,由於自己的不足,過得十分艱難。在各大公司的筆試題中,動態規劃是一個必考點。突然冒出一個想法,寫一個“動態規劃從入門到精通”系列,與各大網友一起交流學習。 學習動態規劃,愚認為,就是解決以下的三個問題: 什麼是動態規劃?什麼時候要用動態規劃?怎麼使

IOS 初級開發入門教程介紹

導讀        目前移動端開發市場上引導開發者追求技多不壓身,一個全棧開發者至少要懂後臺伺服器、資料庫、Android、web、ios開發等。“一超多強”是指開發者先成為一門技術的專家然後掌握瞭解多門技術,這是一種好的發展趨勢,另外,這種技多不壓身我認為當開發者更適合發

反射入門精通

輸出結果 reflect file 加載器 mysql 構造 app throw 檢查 1. 三個類加載器 BootStrap類加載器【boot】 用於加載 jre:lib下的jar包【.class文件】 Java提供的大多數類都在此 Exetension類加載器【

linux入門精通

scp 我的電腦 test 修改 linux 改名 人性 -- ces 1. 虛擬機的安裝 2. 虛擬機設置 註: 如果選擇的是NAT模式   匹配的網卡是:   通過這個虛擬的網卡與本機進行通信,只能與本機進行通信,如果本機可以訪問互聯網,該虛擬機也可以訪問互

javascript入門精通

png var 技術 date 入門 logs function con undefine 1. heap:堆 引用值stack: 棧 先進後出 裏面的值是copy的關系 不可改變的原始值:Number String Boolean undefined null

python-類-入門精通

0.什麼是類 類(Class)是面向物件程式設計(OOP,Object-Oriented Programming)實現資訊封裝的基礎。類是一種使用者定義型別,也稱類型別。每個類包含資料說明和一組操作資料或傳遞訊息的函式。類的例項稱為物件。 面向物件程式設計是最有效的軟體編寫方法之一。在面向物

Matlab入門精通

1、查詢與刪除記憶體變數 在指令視窗(Command Window)中執行who、whos查詢MATLAB的記憶體變數.這兩個指令的差別僅在於獲取記憶體變數資訊的簡單和詳細程度不同. clear        &

Spark入門精通

什麼是Spark 大資料計算框架 離線批處理 大資料體系架構圖(Spark) Spark包含了大資料領域常見的各種計算框架:比如Spark Core用於離線計算,Spark SQL用於互動式查詢,Spark Streaming用於實時流式計算,Spark MLib用於機器學習,Spark

springboot入門精通

需要 ati works thymeleaf run work jpa ring 無需 springboot到底有什麽好處?有什麽優勢?這個先不用看,我們只要知道它有很多優勢,現在要做的事只有一件,那就是擼代碼!擼完就知道有多少料! 首先,在案例中,我們會構建一個英雄列表

Java演算法入門精通

認識時間複雜度     常數時間的操作:一個操作如果和資料量沒有關係,每次都是 固定時間內完成的操作,叫做常數操作。     時間複雜度為一個演算法流程中,在最差的資料情況下,常數運算元量的指標。常用O (讀作big O)來表示。具體來說,在常數運算元量的表示式中, 只要

海思Hi3519A MPP入門精通

1. 概述 海思提供的媒體處理軟體平臺(Media Process Platform,簡稱 MPP),可支援應用軟體快速 開發。該平臺對應用軟體遮蔽了晶片相關的複雜的底層處理,並對應用軟體直接提供 MPI(MPP Program Interface)介面完成相應功能。該平臺支援應用軟體快速開發以

Go入門精通go語言初識

 一、第一個go程式package main import ( "fmt" ) func main(){ fmt.Println("hello world") }對於程式碼的解釋如果是為了將程式碼編譯成一個可執行程式,那麼package必須是m

攝影后期入門精通

博主又回來了,由於眾所周知的原因,最近有點想放棄玩航拍(玩航拍兩年左右了),這兩天迷上了單反,之前又懂一點photoshop之類的軟體,博主準備學習一下攝影和後期,在這裡寫點筆記 相機的選擇 品牌 天朝內的相機品牌,耳熟能詳的有:佳能、尼康、索

Android開發中ConstraintLayout的使用入門精通

前段時間發現Android Studio在新建 Activity 的時候,預設生成的佈局檔案的根佈局變成了 ConstraintLayout ,不過由於以前的幾種佈局檔案都是用習慣了,所以往往都是直接修改根佈局,最近覺得有必要學習一下這種佈局的使用,畢竟 google 都推薦使用,所以就把我

TensorFlow 入門精通:安裝和使用

安裝過程 目前較為穩定的版本為 0.12,本文以此為例。其他版本請讀者自行甄別安裝步驟是否需要根據實際情況修改。 TensorFlow 支援以下幾種安裝方式: PIP 安裝 原始碼編譯安裝 Docker 映象安裝 PIP 安裝

CUDA入門精通:環境搭建

NVIDIA於2006年推出CUDA(Compute Unified Devices Architecture),可以利用其推出的GPU進行通用計算,將平行計算從大型叢集擴充套件到了普通顯示卡,使得使用者只需要一臺帶有Geforce顯示卡的筆記本就能跑較大規模的並行處理程式

ActiveMQ入門精通

這是關於訊息中介軟體ActiveMQ的一個系列專題文章,將涵蓋JMS、ActiveMQ的初步入門及API詳細使用、兩種經典的訊息模式(PTP and Pub/Sub)、與Spring整合、ActiveMQ叢集、監控與配置優化等。話不多說,我們來一起瞧一瞧!JMS首先來說較早以前,也就是沒有JMS的那個時候,很

Intellij IDEA 入門精通

開心一笑 【一位大學教授對學生講道:“古代‘呂’是接吻的意思,口對口,很形象;”其中一學生問道:“如果‘呂’是接吻的意思,那麼‘品’宇又怎麼解釋,三個人在一起接吻嗎?”教授正待發怒,又一個同學起說:“我看‘品’字還好解釋,‘器’宇呢?四個人和一隻狗在幹什麼?”

react.js入門精通

web端三大框架react、vue和angular,下面是對react.js的一些總結。 一、環境搭建 1、npm搭建專案 推薦使用npm搭建專案環境,如果網速過慢,可是使用cnpm進行專案的搭建(cnpm是淘寶的npm映象,與npm有些差異,有些模組無法下載或無法正常

RabbitMQ 入門精通

目錄 1. 初識RabbitMQ 2. AMQP 3.RabbitMQ的極速入門 4. Exchange(交換機)詳解 4.1 Direct Exchange 4.2 Topi