和acwing 323. 戰略遊戲這題非常類似,但又有些不同
acwing 323. 戰略遊戲在一條道路的兩個結點至少有乙個是放的,而這題不一定,比如
1
/ | \
2 3 4
/ |5 6
我們可以在3,4,5,6號點放,其他各點都不放。這樣邊1-2的兩個端點都沒有守衛,這就和acwing 323. 戰略遊戲這題不同了
不過稍微觀察可以發現,acwing 323. 戰略遊戲這題的切入點是邊,而本題的切入點是宮殿,也就是樹上的結點。那麼可以用再在不放這個狀態上增加乙個狀態,即
有了狀態表示,接下來j就是推導狀態轉移了,記j為u的子結點,那麼
f [u
][0]
=∑j=
0umi
nf[u][0] = \sum_^u min \lbrace f[j][1], f[j][2]\rbrace
f[u][0
]=∑j
=0u
min。含義:當前結點u
不放且被父節點看到,那麼子結點j
只能放或者被其子結點看到。因為u不放所以不能拿f[j][0]
來更新
f [u
][1]
=f[k
][2]
+∑mi
nf[u][1] = f[k][2] + \sum min \lbrace f[j][1], f[j][2]\rbrace
f[u][1
]=f[
k][2
]+∑m
in。含義:當前結點u
不放,u
的子結點k
放了,u
的其他子結點j
放(f[j][2]
)或者不放(即f[j][1]
)。沒有f[j][0]
的原因也是因為u
不放,且需要列舉k。
f [u
][2]
=∑j=
0umi
nf[u][2] = \sum_^u min \lbrace f[j][0], f[j][1], f[j][2]\rbrace
f[u][2
]=∑j
=0u
min。含義:當前結點放了,那麼子結點取哪種狀態都可以
1,3實現起來比較容易,至於2的實現,詳情見**注釋
#include
#include
using
namespace std;
const
int n =
1510
;int h[n]
, e[n + n]
, ne[n + n]
, idx;
int n, w[n]
;int f[n][3
];void
add(
int a,
int b)
void
dfs(
int u,
int father)
f[u][1
]=1e9;
//依次假設每個結點放, sum - min(f[j][1], f[j][2])就是其他所有結點的放和不放最小值之和
//我們很驚奇地發現,f[u][0]就已經計算過了這個sum,可以拿f[u][0]來代替sum,但為了語義明確,使用sum來表示更合理
for(
int i = h[u]
;~i; i = ne[i])}
intmain()
}//建立雙向邊,從任意乙個結點開始
dfs(1,
0); cout <<
min(f[1]
[1], f[1]
[2])
<< endl;
return0;
}
Acwing 1077 皇宮看守
題目描述 太平王世子事件後,陸小鳳成了皇上特聘的御前一品侍衛。皇宮各個宮殿的分布,呈一棵樹的形狀,宮殿可視為樹中結點,兩個宮殿之間如果存在道路直接相連,則該道路視為樹中的一條邊。已知,在乙個宮殿鎮守的守衛不僅能夠觀察到本宮殿的狀況,還能觀察到與該宮殿直接存在道路相連的其他宮殿的狀況。大內保衛森嚴,三...
ACWing 1077 皇宮看守
太平王世子事件後,陸小鳳成了皇上特聘的御前一品侍衛。皇宮各個宮殿的分布,呈一棵樹的形狀,宮殿可視為樹中結點,兩個宮殿之間如果存在道路直接相連,則該道路視為樹中的一條邊。已知,在乙個宮殿鎮守的守衛不僅能夠觀察到本宮殿的狀況,還能觀察到與該宮殿直接存在道路相連的其他宮殿的狀況。大內保衛森嚴,三步一崗,五...
AcWing 1077 皇宮看守
原題鏈結 考察 樹形dp 這道題戰略遊戲要求看到所有的邊,本題要求看到所有的點 沒想出來,參考了大佬的思路 照搬大佬的思路 設樹上某點u能被看見,這個點要麼自己安插士兵,要麼父節點安插士兵,要麼子節點安插士兵.設f u,st 表示u的st狀態的最小花費.st 0時,它u被父節點看見,st 1,u被子...