洛谷P1430 序列取數 dp

2022-09-01 09:48:14 字數 3560 閱讀 6390

給定乙個長為n的整數序列,由a和b輪流取數(a先取)。每個人可從序列的左端或右端取若干個數(至少乙個),但不能兩端都取。所有數都被取走後,兩人分別統計所取數的和作為各自的得分。假設a和b都足夠聰明,都使自己得分盡量高,求a的最終得分。

時限3s3s

,顯然是要乙個常數小的o(t

n2)o

(tn2

)的方法。

由於每次a和b都只可以在左右兩端取數,所以取完後剩餘的一定是乙個連續的子區間。

正序做似乎不是很好做,考慮倒序,將問題轉化成乙個區間問題。

先考慮最暴力的方法,若先手取時剩餘區間為[l,

r][l

,r],那麼後手一定是取了[x,

r][x

,r]或[

l,x]

(l<

x[l,x

](l<

x,然後先手取[l,

x−1]

[l,x

−1]或[

x+1,

r][x

+1,r

]。設dp

[i][

j]dp

[i][

j]表示先手取成[l,

r][l

,r]的最優答案,那麼這個答案一定由後手的最劣方案轉移而來。因為若後手取後的區間和為s′s

′,區間[l,

r][l

,r]的和為s

s,那麼先手取的和為s−s

′s−s

′。我們要讓s−s

′s−s

′盡量大,那麼就讓s′s

′盡量小即可。即後手的最劣方案。

所以轉移方程就是dp

[i][

j]=s

um[j

]−su

m[i−

1]−m

in(0

,dp[

i][i

],dp

[i][

i+1]

,...

,dp[

i][j

−1],

dp[j

][j]

,dp[

j−1]

[j],

...,

dp[i

+1][

j])d

p[i]

[j]=

sum[

j]−s

um[i

−1]−

min(

0,dp

[i][

i],d

p[i]

[i+1

],..

.,dp

[i][

j−1]

,dp[

j][j

],dp

[j−1

][j]

,...

,dp[

i+1]

[j])

其中sum[

i]su

m[i]

為a[i]

a[i]

的字首和,sum

[j]−

sum[

i−1]

sum[

j]−s

um[i

−1]即∑

k=ij

a[k]

∑k=i

j​a[

k];加上0的原因是因為先手可以一次把所有選完,那麼後手就不能選,即選的和為0。

這樣單次詢問的複雜度是o(n

3)o(

n3)的。

看到方程中有min

min,m

inmi

n需要o(n

)o(n

)的複雜度,但是dpd

p中的min

min一般都是可以進行轉移的。所以可以通過轉移min

min來去掉這個o(n

)o(n

)。設f[

i][j

]=mi

n(dp

[i][

i],d

p[i]

[i+1

],..

.,dp

[i][

j]),

g[i]

[j]=

min(

dp[j

][j]

,dp[

j−1]

[j],

...d

p[i]

[j])

f[i]

[j]=

min(

dp[i

][i]

,dp[

i][i

+1],

...,

dp[i

][j]

),g[

i][j

]=mi

n(dp

[j][

j],d

p[j−

1][j

],..

.dp[

i][j

])。方程就變成了dp

[i][

j]=s

um[j

]−su

m[i−

1]−m

in(0

,f[i

+1][

j],g

[i][

j−1]

)dp[

i][j

]=su

m[j]

−sum

[i−1

]−mi

n(0,

f[i+

1][j

],g[

i][j

−1])

f,gf

,g的維護都是最最最最基礎的了。顯然有f[i

][j]

=min

(f[i

+1][

j],d

p[i]

[i])

f[i]

[j]=

min(

f[i+

1][j

],dp

[i][

i]),g

g同理。

這樣單次詢問的複雜度就降到了o(n

2)o(

n2)。總時間複雜度就是o(t

n2)o

(tn2

)。而且區間dpd

p的常數好像還是122

1​?

#include

#include

#include

using

namespace std;

const

int n=

1010

;int t,n,a[n]

,sum[n]

,dp[n]

[n],f[n]

[n],g[n]

[n];

intmain()

for(

int i=n-

1;i>=

1;i--

)for

(int j=i+

1;j<=n;j++

)printf

("%d\n"

,dp[1]

[n]);}

return0;

}

洛谷 P1430 序列取數

給出乙個序列,兩人輪流從一端開始取任意個數,最後所取數的和即為得分,兩人都想要較高得分,則先去者的最高得分是多少。首先不難想到用dp i j 表示序列剩下從i到j這段時的最高得分,這樣的話有n 2種狀態,n的狀態轉移,總複雜度為n 3,會t。因此可以考慮記錄下述值 le i j 表示從左邊開始取,剩...

洛谷P1430 序列取數

給定乙個長為n的整數序列 n 1000 由a和b輪流取數 a先取 每個人可從序列的左端或右端取若干個數 至少乙個 但不能兩端都取。所有數都被取走後,兩人分別統計所取數的和作為各自的得分。假設a和b都足夠聰明,都使自己得分盡量高,求a的最終得分。輸入格式 第一行,乙個正整數t,表示有t組資料。t 10...

洛谷P1430 序列取數

題目大意 給定乙個序列 s 每個人每輪可以從兩端 任選一端 取任意個數的整數,不能不取。在兩個人都足夠聰明的情況下,求先手的最大得分。題解 設 f 表示剩下 i,j 先手的最大得分。令 sum sum limits j s k therefore f sum min i f min limits j...