tyvj 4869 罪犯分組 狀壓DP

2021-08-09 07:42:37 字數 918 閱讀 4265

炸一看題目,無向圖?矛盾關係?難道是個圖論?

顯然,資料範圍打消了我的顧慮。16?顯然是狀態亞索。

不過之後就卡這了,但經過oblack的一番指導(ob真是太棒了),終於凌晨在寢室裡用手機a了這道。

f[s]記錄當前已處理的罪犯集合的最小小組數量。

對於狀態s,列舉記錄集合中罪犯的矛盾數,若滿足條件,則就可以分為一組,即f[s]=1;

最後用j來列舉s的子集,找到min(f[j]+f[j^i])即可。

#include

#include

#include

#include

using

namespace

std;

const

int maxn=20;

const

int sums=1

<<17;

bool rel[maxn][maxn];

int m,n,maxk,i,j,k,f[sums];

int main()

for(i=0;i

for(j=0;jfor(k=j;kif(rel[j][k]&&(i&(1

<1

for(j=i;j;j=i&(j-1))

}printf("%d",f[(1

<1]);

}

TYVJ4869 罪犯分組 狀壓DP列舉子集

資料範圍這麼小,很容易考慮到狀壓dp。預處理出所有情況的罪犯矛盾數並判斷哪些狀態是不合法的。之後就轉換為了乙個比較簡單的揹包dp問題。狀態轉移方程 f s m in f i 1 i 為s的子 集,且i xors 表示的集 合中矛盾 數不超過 k 問題似乎解決了,但是有乙個問題 如何高效列舉s的子集?...

TYVJ P4869 罪犯分組 狀態壓縮DP

i 表示 i 這個狀態最少能分多少組,列舉狀態,用它的子集更新狀態就可以了。子集列舉。顯然可以列舉所有小於等於該狀態的數,但還有更快的方法 比如列舉狀態x的所有子集,可以這樣寫 for int i x i i i 1 x i就為x的所有子集。感性的理解 x中某位為1,子集中該位為0或1 x中某位為0...

關押罪犯 並查集 二分

s 城現有兩座監獄,一共關押著n 名罪犯,編號分別為1 n。他們之間的關係自然也極不和諧。很多罪犯之間甚至積怨已久,如果客觀條件具備則隨時可能爆發衝突。我們用 怨氣值 乙個正整數值 來表示某兩名罪犯之間的仇恨程度,怨氣值越大,則這兩名罪犯之間的積怨越多。如果兩名怨氣值為c 的罪犯被關押在同一監獄,他...