題目描述
mm 雖然一輩子只要乙個,但是也得早點解決。於是,n 個光棍們自發組成了乙個光棍組織 (ruffian organization,by wind 亂譯)。現在,光棍們打算分成幾個小組,並且分頭為 找 mm 事
業做貢獻(for example:searching,hunting……by wind 亂譯)。 對於這 n 個光棍的任意乙個組合,都有乙個被稱為「和諧度」的東西,現在,他們想知道, 如何分組
可以使和諧度總和最大。 每個光棍都必須屬於某個分組,可以乙個人一組。
輸入格式
第 1 行為 n,接下來 2^n-1 行,按照 2 進製給出每個分組的和諧度。
(比如接下來第 5 行,也就是總共第六行,2 進製為 00000101,則表示第 1 個人和第 3 個人 這個分
組的和諧度,第 31 行則為 1~5 在一起的和諧度)
輸出格式
僅 1 行,為最大和諧度和。
首先,需要引入乙個子集的概念。
當乙個二進位制數s
ss,若sor
k=
ss\ or\ k=s
sork=s
且k ≠s
k≠sk̸
=s,我們則稱k
kk是s
ss的乙個子集。
也可以這麼理解,乙個二進位制數的子集是這個數將若干個1
11變成000。
子集的**如下:
for
(int j=
(i-1
)&i;j;j=
(j-1
)&i)
這句話用j
jj來列舉i
ii的子集。至於這句話具體的含義我也沒有理解。
子集的乙個性質就是可以直接用i−j
i-ji−
j,即j
jj表示i
ii的子集,i−j
i-ji−
j表示剩下的集合。
寫下來回歸本題:
我們可以直接設f[i
]f[i]
f[i]
表示所有組團中,組團狀態為i的最大價值。
在所有已經組團的隊伍中,組了隊的人為1
11,沒組隊的人為000。
現在考慮狀態轉移方程,每乙個狀態一定都是若干個它的子集組合而成的,所以:
f [i
]=ma
x(f[
j]+f
[i−j
])
f[i]=max(f[j]+f[i-j])
f[i]=m
ax(f
[j]+
f[i−
j])由於集合是順序列舉的,列舉i
ii時i−j
i-ji−
j的狀態已經被列舉到了。
**如下:
#include
using
namespace std;
int n;
int f[
1<<17]
;int
main
(void
)
TYVJ4869 罪犯分組 狀壓DP列舉子集
資料範圍這麼小,很容易考慮到狀壓dp。預處理出所有情況的罪犯矛盾數並判斷哪些狀態是不合法的。之後就轉換為了乙個比較簡單的揹包dp問題。狀態轉移方程 f s m in f i 1 i 為s的子 集,且i xors 表示的集 合中矛盾 數不超過 k 問題似乎解決了,但是有乙個問題 如何高效列舉s的子集?...
關於狀壓DP列舉子集的方法與理解
題外話 剛才發現自己已經不記得如何列舉乙個狀壓集合的子集 因為之前本身就沒有怎麼理解列舉子集的方法完全就是背下來的所以忘掉很正常 所以寫下這篇部落格做個提醒或者叫做警示吧,很多東西還是要理解透徹不然會吃虧的。希望這篇部落格可以對博友們一些幫助,當然如果有錯歡迎指出。我們現在要列舉狀壓集合s ss的子...
狀態壓縮動態規劃(狀壓DP)
狀態壓縮動態規劃就是我們常說的狀壓dp,前兩天某廠實習生二面面試官隨手就給我抽了一道狀壓dp的題,我根本沒思路,sorry就寫了一行注釋。然後leetcode周賽最後一題又碰到了狀壓dp的題目,我一定要搞定這個型別的問題。加油加油 狀壓dp說簡單也簡單,基本上就是用一串二進位制樹來表示當前情況 的狀...