原題鏈結
考察:樹形dp
這道題戰略遊戲要求看到所有的邊,本題要求看到所有的點
沒想出來,參考了大佬的思路
照搬大佬的思路:
設樹上某點u能被看見,這個點要麼自己安插士兵,要麼父節點安插士兵,要麼子節點安插士兵.設f[u,st]表示u的st狀態的最小花費.st==0時,它u被父節點看見,st==1,u被子節點看見,st==2時,u自己安插了士兵.
根據以上可以寫出轉移方程(由子節點推父節點):
f[u,0] += min(f[v][1],f[v][2])(v是u的子節點,v要麼被自己的子節點看見,要麼自己就安插了士兵)
f[u,1] += min(f[k][2]+min(f[v][1],f[v][2])(k是自己安插士兵的花費最小的子節點,而v是其他子節點)
f[u,2] += min(f[v][1],f[v][2],f[v][0])(三種都有可能)
注意:由所有子節點的情況推出父節點,因為父節點需要所有子節點情況成立才成立.
但是這道題需要求出的是f[v][2]-min(f[v][1],f[v][2])的最小值,如果直接求f[v][2]的最小值會wa.關於原因這裡有詳細證明 go
1 #include 2 #include 3 #include 4 #include 5using
namespace
std;
6const
int n = 1510,inf = 0x3f3f3f3f;7
inth[n],w[n],idx;
8int f[n][3];9
bool
has_fa[n];
10struct
roadroad[n*n>>1
];13
void add(int a,int
b)14
17void dfs(int
u)18
31if(res1]=min(f[u][0]+res,f[u][1
]);32}33
intmain()
3448}49
while(has_fa[root]) root++;
50dfs(root);
51 printf("
%d\n
",min(f[root][1],f[root][2
]));
52return0;
53 }
2021.4.7 第二次寫的時候,不知道為啥把父節點也考慮進去了,私以為dp推轉移方程的時候,就是只考慮前一狀態和當前狀態,將當前狀態當作最終狀態.
Acwing 1077 皇宮看守
題目描述 太平王世子事件後,陸小鳳成了皇上特聘的御前一品侍衛。皇宮各個宮殿的分布,呈一棵樹的形狀,宮殿可視為樹中結點,兩個宮殿之間如果存在道路直接相連,則該道路視為樹中的一條邊。已知,在乙個宮殿鎮守的守衛不僅能夠觀察到本宮殿的狀況,還能觀察到與該宮殿直接存在道路相連的其他宮殿的狀況。大內保衛森嚴,三...
AcWing 1077 皇宮看守
和acwing 323.戰略遊戲這題非常類似,但又有些不同 acwing 323.戰略遊戲在一條道路的兩個結點至少有乙個是放的,而這題不一定,比如 1 2 3 4 5 6我們可以在3,4,5,6號點放,其他各點都不放。這樣邊1 2的兩個端點都沒有守衛,這就和acwing 323.戰略遊戲這題不同了 ...
ACWing 1077 皇宮看守
太平王世子事件後,陸小鳳成了皇上特聘的御前一品侍衛。皇宮各個宮殿的分布,呈一棵樹的形狀,宮殿可視為樹中結點,兩個宮殿之間如果存在道路直接相連,則該道路視為樹中的一條邊。已知,在乙個宮殿鎮守的守衛不僅能夠觀察到本宮殿的狀況,還能觀察到與該宮殿直接存在道路相連的其他宮殿的狀況。大內保衛森嚴,三步一崗,五...