線性動態規劃 最長不下降子串行(LIS)

2021-10-25 14:18:42 字數 3036 閱讀 6461

我們知道,遞推就是按照遞推公式不斷往前求解的乙個過程,對於當前,只有乙個狀態描述當前的值。若某些問題並非由乙個狀態而是由多個狀態不斷推導,那麼這種方法就是動態規劃,簡稱dp。動態規劃是運籌學的乙個分支,是將問題分解成各個階段,由相鄰的兩個階段根據狀態轉移方程推到求解的一種方法。

所謂的線性動態規劃,就是該問題模型是線性的,資料結構表現為線性表的形式。

題幹:

最長不下降子串行。給定乙個長度為n的序列a,求出這個序列中最長不下降子串行,所謂最長不下降子串行,就是對於i輸出樣例:

3

38 55 70

本題給出的是乙個序列,若將該序列的每乙個數看成乙個點,則資料模型就是乙個線性佇列。

設f[ i ]表示到當前第i個元素為止最長不下降子串行長度,對於當前的第i個元素,考慮到跟之前哪乙個子串行能繼續構成不下降序列,從而選取決策。有如下狀態轉移方程

f[ i ] = max 滿足 j#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

using namespace std;

#define ll long long

#define ios ios::sync_with_stdio(false) , cin.tie(0) , cout.tie(0);

#define mem(a,b) memset(a,b,sizeof(a))

const

int n=

5005

;const

int inf=

0x3f3f3f3f

;int n,len,a[n]

,f[n]

,pre[n]

,ans[n]

;//f為狀態描述,pre記錄決策值

intmain()

int tail =0;

for(

int i=

1;i<=n;i++)if

(f[tail]

) tail = i;

//找到最長子序列的位置

for(

;tail;tail=pre[tail]

) ans[

++len]

=tail;

//將最優子串行逆序放入ans中

cout

while

(len) cout<<<

" ";

//輸出子串行

cout

}上述演算法時間複雜度為o(n * n),對於該題,若資料再大一點,則會超時。我們這裡可以利用有序佇列優化到時間複雜度為o(n * logn)

我們再來觀察一下這個狀態轉移方程:

f(i) = max 其中 ji12

3456

78a[ i ]

3827

5530

2970

5865

f[ i ]11

2223

34這裡的j,是找到1~i之間的所有j,其實這裡面有很多是無效的查詢,那麼我們能否快速查詢到我們所要更改的j呢?

更新需要滿足兩個條件:

以上兩個條件提示我們,後面的值一定要大於等於前面的值。因此我們試著按f[ i ]的增序構建乙個a[ i ]不下降的佇列。構建過程如下表所示:i1

2345

678說明

a[ i ]

3827

5530

2970

5865

i=138

f = 1

i=227

f =1, 27<38,替換38

i=327

55f=2

i=427

30f=2,30<55,替換55

i=527

29f=2,29<30,替換30

i=627

2970

f=3i=7

2729

58f=2,58<70,替換70

i=827

2958

65f=4

可以看出,每對一次掃瞄,我們都是再有序佇列查詢相應的新增或者更新的位置。因此有序佇列的二分查詢的時間複雜度為 o(logn) ,所以該演算法的時間複雜度為o(n * logn)

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

using namespace std;

#define ll long long

#define ios ios::sync_with_stdio(false) , cin.tie(0) , cout.tie(0);

#define mem(a,b) memset(a,b,sizeof(a))

const

int n=

100001

;const

int inf=

0x7f

;int

solve

(int a,

int n)

else

}return best;

}int

main()

printf

("%d\n%d\n"

,solve

(a,n));

return0;

}

動態規劃 最長不下降子串行

參考 每一次從頭掃瞄找出最佳答案。int a maxn d maxn intdp return ans 參考了這篇文章 那麼 如下 for int i 0 i n i scanf d a i memset dp,0x1f sizeof dp mx dp 0 for int i 0 i n i ans...

最長不下降子串行 動態規劃

一。問題描述 給定乙個序列a1 a2 a3 an現要求你從中找到最長的不下降子串行 二。問題分析 該問題可以和之前的max sum問題模擬,如果從決策的角度入手,直接引入並定義狀態f i 為 a i 所在子串行到i的長度 那我們的決策策略應該就是使得 f i 最大 所以基於這個分析我們很容易列出動態...

動態規劃 最長不下降子串行LIS

找出一組資料中最長的不下降子串行的長度。1,連續情況。即必須要求子數列連續相依 1 2 3 1 2 7 9中的最長子串行為3 1,2,3 易得遞推公式 if f i f i 1 dp i dp i 1 1 else dp i 1 includeusing namespace std define m...