有 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...