題目鏈結
題意:給定 k
kk 個數,求所有長度為 n
nn 且最長上公升子串行的排列為給定的 k
kk 個數的方案數。
n
<=15
n<=15
n<=1
5
首先想到可以用狀壓解決排列的順序問題,而僅通過 0,10,10,
1 無法表達出最長上公升子串行的長度,而再開一維進行表示也無法進行有效轉移。那麼考慮在求是 lis
lisli
s 時我們會對乙個陣列不斷進行覆蓋,每個數字會逐個填入或被覆蓋,那麼如果我們用0,1
,2
0,1,2
0,1,
2 三個狀態分別表示未用、已用、已被覆蓋,即可通過此得到最長上公升子串行的長度及其他序列資訊,並可以輕鬆轉移。而考慮到複雜度 o(n
3n
)o(n3^n)
o(n3n)
已經很大,在對每個三進製狀態進行列舉時,按從小到大的順序進行列舉,另乙個計算最長上公升子串行長度的指標滿足單調性,因此不會增加額外複雜度。
#include
using
namespace std;
const
int inf=
0x3f3f3f3f
;int dp[
15000000];
int is[20]
,pre[20]
,ppow[20]
,a[20
],lis[20]
;int
main()
ppow[1]
=is[0]
=1;for
(int i=
2;i<=n+
1;i++
) ppow[i]
=ppow[i-1]
*3;int res=0;
dp[0]
=1;for
(int i=
0;i<
(ppow[n+1]
);i++)if
(tot==n)
lis[cnt]
=inf;
int k=1;
for(
int j=
1;j<=n;j++)}
cout<}
BZOJ 3591 最長上公升子串行
哎我還是太菜了,這麼短的 斷斷續續 調了好久。看資料範圍 大概就是狀壓dp 題目名字是 最長上公升子串行 可以猜測是拿跑li s 的單調棧搞搞。那麼可以設計乙個狀態f a b 表示已選集合 a 其中 b是當前單調棧裡的元素,顯然棧裡的元素公升序排列,不用額外加一維狀態表示棧中元素的排列。顯然這可以優...
BZOJ3591 最長上公升子串行
考慮我們做最長上公升子的過程,維護乙個單調棧,每次加入乙個元素,替換掉最前面乙個比他大的數 我們可以dp這個加入元素的過程,用乙個3進製的狀態表示每個數在不在佇列裡且在不在棧裡,可以用o n22n o n 22n 預處理對於棧中的每個狀態,加入乙個新的數之後的狀態 然後做乙個o n3n o n 3n...
BZOJ3591 最長上公升子串行 狀壓DP
description 給出1 n的乙個排列的乙個最長上公升子串行,求原排列可能的種類數。sample input53 1 3 4 sample output 11挺好的dp題。我們先考慮普通lis,我們維護乙個序列,每一次盡量去替換序列中的值。對於這個,可以用乙個三進製維護,0表示未進佇列,1表示...