學術篇 SDOI2008 山賊集團

2022-07-22 05:42:12 字數 2349 閱讀 7269

今天一月一號..

突然想安利一波我的中二的2017總結...

傳送門1:codevs

傳送門2:luogu

時限5s和1s的區別(你沒看我傳送門都給的大牛分站了)

現在不僅線篩.. 有負數的快讀都打不對了..

來比較一下他們的區別?

inline int gn(int a=0,char c=0,int f=1)

inline int gn(int a=0,char c=0,bool f=1)

inline int gn(int a=0,char c=0,bool f=1)

emmmm 於是就愉快的殘掉了..

好吧回到正題.

這個題網上的題解好少啊ovo

畢竟bzoj有10道sdoi2008, 這題就屬於被忽略的題目之一...

不知道為什麼...

資料範圍\(p<=12\)一眼狀壓...

我們可以用12位二進位制表示乙個集合...

這樣定義狀態\(f_\)為第\(i\)個節點上安排集合\(s\)的狀態...

這樣的話\(s\)就是每個兒子和安排在該點的集合們的並集...

但是很多個兒子差集就不好取了, 考慮多叉樹轉二叉樹...

然而似乎傳統的左兒子右兄弟是不行的... 我們考慮另一種轉化方式..

比如我們有一棵這樣的樹:

轉成一棵抉擇方案等價的樹是這樣的:

這裡我們對於有多個子樹的節點, 建立虛擬節點(注意:虛擬節點是不能安排集合的)

如果有好多子樹就繼續遞迴下去(比如如果1有2 3 4 5四個子樹, 那麼就在10的右兒子掛乙個12, 然後把4 5分別放在12的左右兒子.

由於有些點不能放集合, 我們定義\(g_\)表示在以\(x\)為根的子樹中不在\(x\)節點安排集合時的最大價值.

這樣我們就可以根據二叉樹寫出狀態轉移方程:

\[f_=\left\

max\-cost_\}+val_s (k\subseteq s),\; x<=n\\

\\ g_,\; x>n

\end\right.\\

g_=max\+f_\}(k\subseteq s)

\]根據這個狀態轉移方程推就行了...

不過好像是有些卡時間的...

我們可以預處理出某個集合的費用\(cost\)和價值\(val\)

然後列舉子集是有技巧的:

for(int k=s;k;k=(k-1)&s)
這樣會快一點... 大約能把複雜度從\(4^n\)降到\(3^n\)左右...

不過要記得特殊處理空集(因為這樣列舉的\(k\)不會到0)

就做完了...

**(壓常數版):

由於壓了常數變得非常醜(本來寫的也沒多好看ovo)...

#include #include #include #define ri register int

const int n=204,p=4100,i=-1061109568;

int f[n][p],g[n][p],du[n>>1];

int w[n][13],val[p],val[p],cost[n][p];

int ch[2][n],n,nn,p,t; bool vis[n];

int a,b,s;

inline int gi(int a=0,char c=0)

inline int gn(int a=0,char c=0,int f=1)

inline int max(const int &a,const int &b)

inline int min(const int &a,const int &b)

void dfs1(int x)

}}int g(int x,int zt);

int f(int x,int zt)

int g(int x,int zt)

return g[x][zt];

}int main()

for(ri i=1;i<=n;++i)

for(ri j=1;j<=p;++j)

w[i][j]=gi();

t=gn();

for(ri i=1;i<=t;++i) dfs1(1);

for(ri i=0;i<1<

printf("%d\n",f(1,(1<

}

SDOI2008 山賊集團 樹上揹包 狀壓

比較經典的一類樹上揹包問題套乙個子集狀壓列舉。注意到代價的計算與所選的點的集合有關,如果我們要統計代價需要狀壓記錄點集,而資料範圍非常配合的給了p 12 p le12 p 12 直接狀壓當前子樹包含的點集。從葉子向根dp,對於t tt個限制,預處理出每乙個點集s ss所產生的收益,並把路徑拆成乙個乙...

SDOI2008 燒水問題

把總質量為1kg的水分裝在n個杯子裡,每杯水的質量均為 1 n kg,初始溫度均為0 現需要把每一杯水都燒開。我們可以對任意一杯水進行加熱。把一杯水的溫度公升高t 所需的能量為 4200 t n j,其中,j 是能量單位 焦耳 如果一旦某杯水的溫度達到100 那麼這杯水的溫度就不能再繼續公升高,此時...

SDOI2008 洞穴勘測

lct維護連通性型別的題目,主要是要搞清楚findroot函式的作用 判斷根是否相同,和並查集裡面的find 函式有異曲同工之妙,如果根相同可以認為兩個點具有連通性。先access打通一道到x的實邊,現在x是深度最大的節點。然後再splay x到根節點,因為它深度最大,這個時候它只有左子樹。所以找它...