某 SCOI 模擬賽 T1 a DP

2021-10-07 02:52:54 字數 2139 閱讀 4064

有 n

nn 個單詞,每個單詞出現 c

ic_i

ci​ 次,現用-.給單詞編碼,要求任意乙個單詞的編碼不是另乙個的字首。設-的權值為 2,.的權值為 1,最小化所有單詞的權值和。n

≤750

n\leq 750

n≤750。

假設我們已經建好了所有單詞的字典樹,顯然出現次數越多的單詞應該掛在越淺的葉子(下文深淺均指帶權的深淺,-邊長度為 2,.邊長度為 1)。故考慮先將 c

ic_i

ci​ 排序,並 dp。

設 f [i

,j,k

,l

]f[i,j,k,l]

f[i,j,

k,l]

表示前 i

ii 層的樹已經確定,並掛上了前 j

jj 個單詞,這一層有 k

kk 個不確定的、下一層有 l

ll 個不確定的點的最優情況,接著列舉這一層有多少個點要掛上單詞,而沒掛上單詞的節點會貢獻到下一層和下下層。這個 dp 是 o(n

5)

o(n^5)

o(n5

) 的。

考慮優化:首先 i

ii 是沒用的,扔了。我們考慮每個 j

jj,它要麼掛在這一層,由 f[j

,k,l

]f[j,k,l]

f[j,k,

l]轉移到 f[j

+1,k

−1,l

]f[j+1,k-1,l]

f[j+1,

k−1,

l];要麼留給之後,由 f[j

,k,l

]f[j,k,l]

f[j,k,

l]轉移到 f[j

,l+k

,k

]f[j,l+k,k]

f[j,l+

k,k]

,並且所有沒被掛的單詞深度會加 1,加上對應的 c

ic_i

ci​ 之和。這個 dp 是 o(n

3)

o(n^3)

o(n3

) 的。由於 j,k

j,kj,

k 的範圍到不了滿的 i

ii,所以有約 1

6\dfrac16

61​ 的常數,可以通過。

**:

#include

using

namespace std;

intgetint()

while

(c>=

'0'&&c<=

'9')

return ans*f;

}const

int n=

760;

int a[n]

;long

long f[2]

[n][n]

;int s[n]

;int

main()

sort

(a+1

,a+n+

1,greater<

int>()

);for(

int i=n;i>=

1;i--

)s[i]

=s[i+1]

+a[i]

;int t=0;

memset

(f,0x7f

,sizeof

(f))

; f[0]

[1][

1]=s[1];

for(

int i=

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

for(

int j=

1;j<=n-i+

1;j++)}

t^=1

;}long

long ans=

0x7f7f7f7f7f7f7f7fll

;for

(int i=

0;i<=n;i++

)for

(int j=

0;j<=n;j++

)ans=

min(ans,f[t]

[i][j]);

cout

}

20200717 SCOI模擬T1(計數)

description 毒瘤出題人給了你乙個由且僅由小寫字母構成的字串,並且多次詢問你一段區間的字元組成的字串中,noi 子串行出現的次數。輸入輸入資料從noi.in讀入 第一行兩個整數n,m表示字串的長度和詢問次數第二行乙個由小寫字母組成的字串s,下標從1開始標號然後一行乙個整數seed,含義請參...

4 21小A模擬賽 T1

description 乙個無限長的01 序列,初始全為0,每次選擇乙個區間 l,r 進行操作,有三種操作 1 l r 將 l,r 中所有元素變成1。2 l r 將 l,r 中所有元素變成0。3 l r 將 l,r 中所有元素異或上1。每次操作後詢問最左邊的0 在哪個位置。input format ...

題解 模擬賽11 26 T1

很容易就能得到每跳一步就是從黑到白或白到黑 所以如果起點和終點全白或全黑,肯定no 如果起點和終點一黑一白,肯定yes 然後我就錯掉了,因為我沒有注意到有可能起點到不了終點 這種情況只會在棋盤較小的情況下出現 所以我用寬搜判斷了一下 code include define maxn 100010 u...