今天一月一號..
突然想安利一波我的中二的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到根節點,因為它深度最大,這個時候它只有左子樹。所以找它...