題目傳送門
狀態表示
\(f[i,0]\):在點 \(i\) 不擺放警衛,且被父結點看到的所有擺放方案的最小花費
\(f[i,1]\):在點 \(i\) 不擺放警衛,且被子結點看到的所有擺放方案的最小花費
\(f[i,2]\):在點 \(i\) 擺放警衛的所有方案的最小花費
狀態轉移
\(f[i,0]=∑min(f[j,1],f[j,2])\)
\(f[i,2]=∑min(f[j,0],f[j,1],f[j,2])\)
\(f[i,1]=min(f[k,2]+\sum\limits_min(f[j,1],f[j,2]) )\)
注意:
計算\(f[i,1]\)時,先把所有兒子的\(min(f[j,1],f[j,2])\)的總和 \(sum\) 計算出來,當使用第 \(k\) 個兒子放警衛時,把第 \(k\) 個兒子的 \(min(f[k,1],f[k,2])\) 減去,便得到了 $\sum\limits_min(f[j,1],f[j,2]) $
#include using namespace std;
const int inf = 0x3f3f3f3f;
/*以下注釋為早期筆記,希望對你有所幫助
狀態機 + 樹形dp問題
狀態表示:
f(i, 0):第i號結點被他的父結點安排的守衛看住的方案數
f(i, 1):第i號結點被他的子結點安排的守衛看住的方案數
f(i, 2):第i號結點自己安排守衛看住的方案數
狀態計算:(j是i的子結點)
f(i, 0) = sum
i是被他父結點看住的,那他的子結點要麼自己看自己,要麼被自己的子結點看住
f(i, 1) = min}
i如果是被子結點看住的,那麼列舉被子結點看住的所有方案,對所有方案求最小值
這裡的sum不包括j==k的情況,因此需要手動額外減去
f(i, 2) = sum + w(u)
i是被自己看住的,那他的子結點可以被父結點看住,可以自己看自己,也可以被自己的子結點看住
*/const int n = 1510;
int n;
int h[n], w[n], e[n], ne[n], idx;
int f[n][3];
bool st[n];
//鄰接表
void add(int a, int b)
void dfs(int u)
for (int i = h[u]; ~i; i = ne[i]) ,再從中減去對應的貢獻即可得到remain ver
f[u][1] = min(f[u][1], f[u][0] + f[j][2] - min(f[j][1], f[j][2]));
}}int main()
}//找到根
int root = 1;
while (st[root]) root++;
//從根開始進行有向圖的樹形dp
dfs(root);
printf("%d\n", min(f[root][1], f[root][2]));
return 0;
}
Acwing 1077 皇宮看守
題目描述 太平王世子事件後,陸小鳳成了皇上特聘的御前一品侍衛。皇宮各個宮殿的分布,呈一棵樹的形狀,宮殿可視為樹中結點,兩個宮殿之間如果存在道路直接相連,則該道路視為樹中的一條邊。已知,在乙個宮殿鎮守的守衛不僅能夠觀察到本宮殿的狀況,還能觀察到與該宮殿直接存在道路相連的其他宮殿的狀況。大內保衛森嚴,三...
AcWing 1077 皇宮看守
和acwing 323.戰略遊戲這題非常類似,但又有些不同 acwing 323.戰略遊戲在一條道路的兩個結點至少有乙個是放的,而這題不一定,比如 1 2 3 4 5 6我們可以在3,4,5,6號點放,其他各點都不放。這樣邊1 2的兩個端點都沒有守衛,這就和acwing 323.戰略遊戲這題不同了 ...
ACWing 1077 皇宮看守
太平王世子事件後,陸小鳳成了皇上特聘的御前一品侍衛。皇宮各個宮殿的分布,呈一棵樹的形狀,宮殿可視為樹中結點,兩個宮殿之間如果存在道路直接相連,則該道路視為樹中的一條邊。已知,在乙個宮殿鎮守的守衛不僅能夠觀察到本宮殿的狀況,還能觀察到與該宮殿直接存在道路相連的其他宮殿的狀況。大內保衛森嚴,三步一崗,五...