我們知道,遞推就是按照遞推公式不斷往前求解的乙個過程,對於當前,只有乙個狀態描述當前的值。若某些問題並非由乙個狀態而是由多個狀態不斷推導,那麼這種方法就是動態規劃,簡稱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...