JLOI2015 戰爭排程

2021-09-29 06:29:12 字數 2977 閱讀 1916

【記憶體限制:256 mib】

【時間限制:1000 ms】

【標準輸入輸出】

【題目型別:傳統】

【評測方式:文字比較】

臉哥最近來到了乙個神奇的王國,王國裡的公民每個公民有兩個下屬或者沒有下屬,這種關係剛好組成乙個 $n$ 層的完全二叉樹。公民 $i$ 的下屬是 $2i$ 和 $2i +1$。最下層的公民即葉子節點的公民是平民,平民沒有下屬,最上層的是國王,中間是各級貴族。

現在這個王國爆發了戰爭,國王需要決定每乙個平民是去種地以**糧食還是參加戰爭,每乙個貴族(包括國王自己)是去管理後勤還是領兵打仗。乙個平民會對他的所有直系上司有貢獻度,若乙個平民 $i$ 參加戰爭,他的某個直系上司 $j$ 領兵打仗,那麼這個平民對上司的作戰貢獻度為 $w_$。若乙個平民 $i$ 種地,他的某個直系上司 $j$ 管理後勤,那麼這個平民對上司的後勤貢獻度為 $f_$,若 $i$ 和 $j$ 所參加的事務不同,則沒有貢獻度。為了戰爭需要保障後勤,國王還要求不多於 $m$ 個平民參加戰爭。

國王想要使整個王國所有貴族得到的貢獻度最大,並把這件事交給了臉哥。但不幸的是,臉哥還有很多 deadline 沒有完成,他只能把這件事又轉交給你。你能幫他安排嗎?

第一行兩個數 $n,m$。

接下來 $2^$ 行,每行 $n-1$ 個數,第 $i$ 行表示編號為 $2^-1+ i$ 的平民對其 $n-1$ 個直系上司的作戰貢獻度,其中第乙個數表示對第一級直系上司,即編號為 $\frac-1+ i}$ 的貴族的作戰貢獻度 $w_$,依次往上。

接下來 $2^$ 行,每行 $n-1$ 個數,第 $i$ 行表示編號為 $2^-1+ i$ 的平民對其 $n-1$ 個直系上司的後勤貢獻度,其中第乙個數表示對第一級直系上司,即編號為 $\frac-1+ i}$ 的貴族的後勤貢獻度 $f_$ ,依次往上。

一行乙個數表示滿足條件的最大貢獻值。

樣例輸入

3

4503

1082

1271

369303

1135

7491289

10054

837826

947699

216389

樣例輸出

6701
對於 $100 \%$ 的資料,$2 \leq n \leq 10, \ m \leq 2^, \ 0 \leq w_, f_ \leq 2000$

做到這道題,已經喪心病狂了。

在紮實的語文功底下 $(90/150 pts)$ ,我只用了 $5 min$ 看懂題目.

然後就開始暴搜......

暴搜思路就是,啥都不管,用 $o(2^)$ 來列舉乙個人到底是去打仗還是後勤,然後計算此時的價值,最後輸出最大價值即可。

暴搜思路人人懂,算算時間明年到。

時間複雜度大概$o(2^)$,你以為這樣就完了?不,還有個計算的常數 $2^n$,所以完整複雜度 $o(2^×2^n)$真是乙個友好的演算法

基於暴搜,我們可以有一些思考

先不考慮 $m$ 的限制。

在這樣一棵樹裡面,平民 $8、9$ 的價值只和他們的所有祖先,也就是 $1、2、4$ 有關

再往上,$4、5$ 的價值只和 $1、2$ 有關

而暴搜複雜度高在何處?

我們做了很多無效的列舉。比如我們要算 $8、9$ 的價值,但是我們卻列舉了 $3、5、6、7......$的狀態,而這單獨對於 $8、9$ 來說,是無效的列舉。

而 $8、9$ 只與他們的祖先有關。

那麼我們為什麼不考慮乙個狀態,存下節點編號,以及其祖先狀態。

那麼乙個十分粗糙的狀態就出來了:

$dp[s][u]$:節點 $u$ 的祖先狀態為 $s$ (二進位制串的狀壓) 時其子樹的最大價值。

而這時我們又要考慮 $m$ 對於此題的限制,再加一維:

$dp[s][u][j]$:節點 $u$ 的祖先狀態為 $s$ (二進位制串的狀壓) 時,其子樹中選了 $j$ 個人去打仗時,這棵子樹的最大價值。

那麼狀轉就是:

$dp[s][u][j]=dp[s'][v_1][x]+dp[s'][v_2][y],x+y=j$

這個狀轉很簡單,現在我們來算一下時間複雜度:

首先,對於乙個深度為 $k$ 的點

把他們乘起來,時間複雜度$o(2^×2×)}^2)=o(2^)$

但是這個複雜度與 $k$ 有關,不準確,考慮每一層有 $2^$ 個節點,那麼我們分層計算時間複雜度

每一層的時間複雜度就是 $o(2^×2^)=o(2^)$

有 $n$ 層,總時間複雜度為 $o(n2^)$

時間複雜度有了,似乎不會超時。

開始碼**,但是會發現乙個很大的問題:好像這個 $dp$ 陣列的空間有點大?

那麼我們要省掉一維,哪一維呢?

發現 $s$ 是十分好表示的,我們可以在 $dfs$ 的時候帶乙個引數 $s$ 來替代掉這一維就可以了。

**見下:膜拜$trymyedge(lj)$大佬

#include #define mz 1000000007

using

namespace

std;

intn, t;

int c[1005][15][2], siz[15

];int dp[2005][1005

];int add[1005][2005][2

];void dfs(int x, int y, int

z)

else

}int

main()

}dfs(

1, 0, 1

);

for (int i = 0; i <= m; i++) ans = max(ans, dp[1

][i]);

printf(

"%d\n

", ans);

return0;

}

JLOI2015 戰爭排程 war

一開始看這題,毫無頭緒 不過發現n十分的小,最多只有10,想一想暴搜加優化。先試著打了打暴搜,從上往下列舉狀態,然後搜尋到子節點的時候,再統計答案,每個父節點的答案是兩個子節點答案的和,dfs x,y,z 表示當前搜到的點二進位制狀態為x,從根節點到底層打仗的狀態為y,然後此時要打仗的人有z個。然後...

題解 JLOI2015戰爭排程

搜尋 狀壓 dp。注意到乙個性質 考慮一棵以x為根的子樹,在x到原樹的根的路徑上的點如果都已經確定了方案,那麼x的左右兒子的決策就彼此獨立,互不影響了。所以我們考慮狀壓一條路徑上每一層節點的狀態,求出dp u x 以u為根的子樹中分配x個作戰平民的最大收益是多少 注意因為是在dfs當中,所以dp陣列...

JLOI2015 戰爭排程 解題報告

感覺一到晚上大腦就宕機了.題目本身不難,就算沒接觸過想想也是可以想到的 這個滿二叉樹的深度很淺啊,每個點只會和它的 n 1 個祖先匹配啊 於是可以暴力列舉祖先鏈的選擇 然後處理某個點 i 時,已經列舉了 i 到根的祖先的選擇 這時候我們發現列舉 i 後,左右兒子的貢獻的獨立的,然後左右兒子的選擇對上...