鏈結給出兩個長度分別為n,m
n,m的數列, 求最長上公升公共子串行的長度
設階段為 i,ji,j 表示第乙個串前i
i個元素與第二個串前j
j個元素 lci
slci
s根據lcs
lcs的轉移方程, 初步得出 :if
(ai=
=bi)
if(a
i==
bi)
. dp[i
,j]=
dp[i
−1][
j−1]
+1dp
[i,j
]=dp
[i−1
][j−
1]+1
else
else
. dp[i
,j]=
max(
dp[i
−1][
j],d
p[i]
[j−1
])dp
[i,j
]=ma
x(dp
[i−1
][j]
,dp[
i][j
−1])
但這是錯誤的, 因為還要求單調遞增, 於是為了方便轉移, 需要額外乙個維度來保證正確性?
設 dp[i
,j,k
]dp[
i,j,
k]表示第乙個串前i
i項與第二個串前jj項l
cisl
cis且最後乙個元素為 k
k可以初步得到if
(ai=
=bj)
if(a
i==
bj)
. dp[i
,j,b
j]=d
p[i−
1,j−
1,bp
]+1d
p[i,
j,bj
]=d
p[i−
1,j−
1,bp
]+1
. els
eels
e. dp[
i,j,
k]=d
p[i−
1,j,
k]dp
[i,j
,k]=
dp[i
−1,j
,k]然而上方的愚蠢行為不知道會引起多少人笑話…
完全可以不要第3維:if
(ai=
=bj)
if(a
i==
bj)
. dp[i
,j]=
dp[i
−1,p
]+1d
p[i,
j]=d
p[i−
1,p]
+1. e
lsee
lse. dp[
i,j]
=dp[
i,j−
1]dp
[i,j
]=dp
[i,j
−1]由於最後要輸出方案, 所以使用pre
pre陣列記錄最優轉移**, 最後遞迴輸出即可
#include
#define reg register
const
int maxn =
505;
int n;
int m;
int a[maxn]
;int b[maxn]
;int dp[maxn]
[maxn]
;int pre[maxn]
[maxn]
;void
print
(int x)
intmain()
}else
if(b[j]
< a[i]
&& maxx < dp[i-1]
[j]) maxx = dp[i-1]
[j], pre = j;}}
int ans =
0, ans_p =0;
for(reg int i=
1; i <= m; i ++)if
(ans < dp[n]
[i]) ans = dp[n]
[i], ans_p = i;
printf
("%d\n"
, ans)
;print
(ans_p)
;return0;
}
CF374 C 動態規劃
題目看上去感覺像是dijstra,但是不是最短路,而是在實踐允許的範圍內選擇最多的點去走完從1到n的路,這個想到的是動態規劃,以邊為核心,一條邊一條邊的掃過,如果這條邊對應的起點和終點連線上之後,對於從1到終點來說是有利的就加上那種,我還不是很理解,只是把標程看懂自己敲了一遍而已。include u...
CF183D T shirt(動態規劃)
洛谷 codeforceso n2m o n 2m 的暴力懶得寫了,比較容易,可以自己想想。做法是這樣的,首先我們發現乙個結論 對於某個顏色 我們就把尺寸當成染色問題好了 如果你拿的個數越多,那麼它對於答案的貢獻就越來越少。這個東西是顯然的,所以這個函式是乙個凸函式。那麼這樣子就可以貪心,每次選擇對...
CF183D T shirt(動態規劃,貪心)
洛谷 codeforces o n 2m 的暴力懶得寫了,比較容易,可以自己想想。做法是這樣的,首先我們發現乙個結論 對於某個顏色 我們就把尺寸當成染色問題好了 如果你拿的個數越多,那麼它對於答案的貢獻就越來越少。這個東西是顯然的,所以這個函式是乙個凸函式。那麼這樣子就可以貪心,每次選擇對於答案貢獻...