題意:每個頂點有兩個權值b和w。最多3000個節點的樹,分成恰好m個非空的連通塊,使得盡可能多的連通塊滿足w的和嚴格大於b的和。
樹上揹包的套路題,這裡揹包 \(dp[i][j]\) 表示以i為根的子樹,已經劃分了 \(j\) 個連通塊,包括根節點在內的最後乙個連通塊沒有劃分,能取到的最優值。
這一題最優值看起來有兩維,但是事實上是乙個pair,假如在子樹中已經取得了x個連通塊「優勢區」,那麼即使子樹中包含根節點在內的是負無窮的「暫時優勢」,都比x-1個優勢區和正無窮的暫時優勢好(因為轉移出x個連通塊還會額外劃分乙個連通塊,並不是轉移到同乙個值)。
注意樹上揹包的siz是最後才加進迴圈裡。
在計算過程中,尚未計算完成的u子樹中的dp,不能急著把根節點劃分出新的塊,要在計算完成後統一加上去。
const int maxn = 3000 + 10;
int n, m;
vectorg[maxn];
int w[maxn], b[maxn];
int siz[maxn];
vectordp[maxn];
pil add(pil a, pil b)
void dfs(int u, int p)
siz[u] += siz[v];
}for (int i = min(siz[u] - 1, m - 1); i >= 0; --i)
cmax(dp[u][i + 1], pil(dp[u][i].first + (dp[u][i].second > 0), 0ll));
}
打掉乙個怪獸要先打掉他的父親,打乙個怪獸的消耗是這個怪獸的hp和其存活的兒子們的hp的和。事先使用i次雷射能打到的最小消耗。
const int maxn = 2000 + 10;
int n;
vectorg[maxn];
int a[maxn];
int siz[maxn];
vectordp[maxn][2];
void dfs(int u, int p)
}siz[u] += siz[v];
}}
dp[u][0][i]:在u子樹中,不使用優惠券購買i個物品的最小**
dp[u][1][i]:在u子樹中,使用優惠券購買i個物品的最小**
const int maxn = 5000 + 10;
int n;
vectorg[maxn];
int c[maxn], d[maxn];
int siz[maxn];
vectordp[maxn][2];
void dfs(int u, int p)
}siz[u] += siz[v];
}}
vector
寫法空間複雜度會節省非常多(最壞情況仍可以節省一半),由於空間壓縮所節省的cache也會使得執行速度提公升。 動態規劃 揹包
揹包經典問題 揹包問題01 乙個揹包容積為t 0 t 2000 現在有n 0 如下 includeusing namespace std int s 1005 bool f 3000 int main 揹包問題02 若每種物品有無限多個。從這n種物品中選取若干個裝入揹包內,使揹包所剩的空間最小。請求...
揹包(動態規劃)
一 01揹包問題 特點 每件物品僅有一件,可以選擇放與不放 有件物品和乙個容量為 的揹包。第 件物品的費用是 價值是 求解將哪些物品裝入揹包可使這些物品的費用總和不超過揹包容量,且價值總和最大。用子問題定義狀態 f i v max f i 1 v f i 1 v c i w i 注意有意義當且僅當存...
動態規劃揹包問題 01揹包
問題描述 n種物品,每種乙個。第i種物品的體積為vi,重量為wi。選一些物品裝到容量為c的揹包,使得揹包內物品不超過c的前提下,重量最大。問題分析 宣告乙個f n c 的陣列。f i j 表示把前i件物品都裝到容量為j的揹包所獲得的最大重量。當 j v i 時,揹包容量不足以放下第 i 件物品,f ...