海亮DAY22 一 線性動態規劃

2021-08-21 11:30:15 字數 3206 閱讀 4022

**:海量集訓-動態規劃

分三次更新

###基本概念:動態規劃(dynamic programming)是運籌學的乙個分支,是求解多階段決策過程最優化的數學方法。(十分抽象)

用圖表示:

(嘔心瀝血的花了我五分鐘的事件啊!)

由上圖可知,想要實現動態規劃,就必須有以下階段:

1、劃分階段

按照時間或空間特徵,有序的或者是可排序的

2 確定狀態和狀態變數

可以表示各個階段時所處於的各種客觀情況,滿足無後效性原則

3 確定決策並寫出狀態轉移方程

根據相鄰兩段的各個狀態之間的關係

4 尋找邊界條件

起始條件,終止條件

並且動態規劃必須滿足以下性質:
1、最優化原理

2、無後效性

簡單的說這兩條原理就是後一種狀態只能由前一種狀態更新,而不能由後一種狀態更新前一種狀態,否則就會造成乙個環,做很多無用功

那麼接下來進入正題:

概念:所謂線性dp(又叫序列dp)就是在乙個給定的序列上進行dp,而因為序列大多都是線性,所以稱為線性dp

它的狀態是可以是一維的,也可以是多維的。本類的狀態是基礎的基礎,大部分的動態規劃都要用到它。

一些基本問題:

一、最長上公升子串行(lis)

題目描述:給定乙個序列,請求出其中嚴格遞增的子串行的長度。
分析:首先我們用乙個f[i]表示1到i的最長上公升子串行的長度。

我們思考,如何進行狀態轉移?

對於當前狀態f[i],可以由之前的狀態f[j]轉移過來,且我們知道,題目所求的是最長上公升序列,我們列舉之前的j時,一旦a[i]>a[j],說明之前的a[j]能與a[i]組成乙個最長上公升序列,即這時f[i]=f[j]+1。這樣,我們只需要求出f[j]的最大值便可。

狀態轉移方程如下:

f [i

]=f[i-1][j-1]+1, & \text \\ max(f[i-1][j],f[i][j-1]), & \text \end

f[i][j

]=a[100001]=

;//結構體,方便排序

int x,y,n;

int dp[

1000001]=

;int maxx=0;

inline

bool

mycmp

(node xx,node yy)

//按左端點從小到大排序

intmain()

printf

("%d"

,maxx)

;return0;

}二、合唱隊形

題目描述: n位同學站成一排,**老師要請其中的(n-k)位同學出列,使得剩下的k位同學排成合唱隊形。

合唱隊形是指這樣的一種隊形:設k位同學從左到右依次編號為1,2…,k,他們的身高分別為t1,t2,…,tk, 則他們的身高滿足t1…>tk(1<=i<=k)。

你的任務是,已知所有n位同學的身高,計算最少需要幾位同學出列,可以使得剩下的同學排成合唱隊形。

#####分析:這道題的演算法已經很明顯了,仍然是最長上公升子串行。基於這個隊形的性質,我們知道以中間的乙個人為分界點,他左邊的同學是乙個最長上公升序列,他右邊的同學是乙個最長下降序列。

#####問題又可以轉化為兩個最長上公升序列:從左到右做一遍lis,在右到左做一遍lis,最後列舉中間點計算最大值即可。

#####計算最多的同學組成的佇列的公式:

m ax

x=ma

x(ma

xx,d

p1[i

]+dp

2[i]

−1)(

1<=i

<=n

)maxx =max(maxx,dp1[i]+dp2[i]-1) (1<=i<=n)

maxx=m

ax(m

axx,

dp1[

i]+d

p2[i

]−1)

(1<=i

<=n

)原式子-1是因為中間點被算了兩次

那麼具體**如下:

#include

using

namespace std;

int n;

int dp1[

1000001]=

;//正著

int dp2[

1000001]=

;//倒著

int maxx=0;

int a[

1000001]=

;int

main()

//正著

for(

int i=n;i>=

1;i--

)//倒著

for(

int i=

1;i<=n;i++

) maxx=

max(maxx,dp1[i]

+dp2[i]-1

);//比較最大值

cout<

//注意,題目問的是去掉多少同學,而不是最多可以組成多長的佇列

return0;

}

三、飛彈攔截

題意簡述:某國為了防禦敵國的飛彈襲擊,發展出一種飛彈攔截系統。但是這種飛彈攔截系統有乙個缺陷:雖然它的第一發炮彈能夠到達任意的高度,但是以後每一發炮彈都不能高於前一發的高度。某天,雷達捕捉到敵國的飛彈來襲,由於該系統還在試用階段,所以只有一套系統,因此有可能不能攔截所有的飛彈。

輸入飛彈的枚數和飛彈依次飛來的高度(雷達給出的高度資料是不大於30000的正整數,每個資料之間有乙個空格),計算這套系統最多能攔截多少飛彈?

如果要攔截所有飛彈最少要配備多少套這種飛彈攔截系統?

分析:這道題有兩個小問,第二個小問屬於貪心,不在這次的範疇,就不多講

第一小問問我們至少能攔截多少個飛彈,題目中說「以後每一發炮彈都不能高於前一發的高度」,這時乙個關鍵句。這句話進行化簡後就是說前乙個數不能大於後乙個數,原問題就轉化為此序列的最長不上公升子串行(是包括相等的),只需要在之前的**中改變乙個符號便可,這裡就不貼**了。

至於第二小問,就是用貪心求序列的最長不下降序列的個數,不多敘述

實習日記 Day22

今天是早起成功並且鍛鍊了的一天 然而 今天也是中午喝完咖啡就睏到趴下的一天 吐槽與接納 坦白講,我最近開始厭倦去找我 了 這種情緒的出現是為什麼呢?因為失望。我懷著求知和解決問題的心態去請教他,但是他常常跟我閒聊或者只講一些無關痛癢的內容。讓我覺得現在跟他學不到那麼多乾貨內容了,感覺自己沒什麼長進。...

每日演算法 day 22

那些你早出晚歸付出的刻苦努力,你不想訓練,當你覺的太累了但還是要咬牙堅持的時候,那就是在追逐夢想,不要在意終點有什麼,要享受路途的過程,或許你不能成就夢想,但一定會有更偉大的事情隨之而來。mamba out 2020.3.6 廣度優先搜尋 include include include includ...

Day 2 2 資料轉換

集合 set 例如 set variable 集合的屬性 1 集合是無序排列的 2 集合有去重功能 集合的方法 交集 差集 並集 補集 怎樣建立乙個空集合 只能用 set 方法建立,用 建立的是字典 字典 用鍵值對表示的集合 語法 dict var 字典中對鍵的要求 可雜湊的資料型別 資料型別 in...