**:海量集訓-動態規劃
分三次更新###基本概念:動態規劃(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...