SDOI2006 保安站崗

2022-03-03 17:51:44 字數 1430 閱讀 1340

看到題目之後——果斷樹形dp啊!!

但是怎麼樹形dp啊qwq。。。。開始想的是\(dp[i][0/1]\)來表示i節點擊不選擇。

那麼狀態轉移方程:

\(dp[i][0]=\sum_^{}dp[v][1]\)

\(dp[i][1]=val[i]+\sum_min(dp[v][0],dp[v][1])\)

然後如果所有小的都是dp[v][0],找乙個最小的dp[v][1]加上,然後減去原先對應加上的。

會被這樣一組簡單的資料hack掉:

91 1 1 2

2 5 3 3 4 5

3 100 1 6

4 100 1 7

5 100 2 8 9

6 1 0

7 1 0

8 1 0

9 1 0

為什麼呢?是因為我們沒有考慮用父親節點控制該節點的情況

所以正確的狀態設計應該是這樣的:

\(dp[i][0]\)表示節點\(i\)至少被父親節點控制。

\(dp[i][1]\)表示節點\(i\)至少被子節點控制。

\(dp[i][2]\)表示節點\(i\)至少被自己控制。

\(dp[i][0]=\sum min(dp[son(i)][1],dp[son(i)][2])\)

\(dp[i][1]=\sum min(dp[son(i)][1],dp[son(i)][2])+dp[son(i)][2]\)

(其中至少有乙個是1)

\(dp[i][2]=\sum min(dp[son(i)][0],dp[son(i)][1],dp[son(i)][2])+val[i]\)

**如下:

#include#include#include#include#include#define maxn 2010

using namespace std;

struct edgeedge[maxn<<1];

int edge_number,n,ans=2147483647;

int val[maxn],head[maxn];

long long dp[maxn][3];

void add(int from,int to)

inline void search(int now,int fa)

dp[now][0]=sum;

dp[now][1]=2147483647;

for(int i=head[now];i;i=edge[i].nxt)

return;

}int main()

}memset(dp,0x3f,sizeof(dp));

search(1,0);

printf("%lld\n",min(dp[1][1],dp[1][2]));

return 0;

}

SDOI 2006 保安站崗

洛谷傳送門 五一來臨,某地下超市為了便於疏通和指揮密集的人員和車輛,以免造成超市內的混亂和擁擠,準備臨時從外單位呼叫部分保安來維持交通秩序。已知整個地下超市的所有通道呈一棵樹的形狀 某些通道之間可以互相望見。總經理要求所有通道的每個端點 樹的頂點 都要有人全天候看守,在不同的通道端點安排保安所需的費...

SDOI 2006 保安站崗

給出一棵 n 個節點以 1 為根的樹,乙個節點的覆蓋半徑是 1 點有點權 val x 選擇一些點,使得點權和最小,同時每個節點要麼被選擇要麼被周圍的點覆蓋。樹形dp 的討論。注意到覆蓋有可能呈現出兩層都沒有選點的情況 下面被子樹覆蓋,上面被父節點覆蓋 所以狀態設計要注意。設 f i 0 1 2 表示...

SDOI2006 保安站崗

傳送門 一道很好的樹型dp。一開始我的狀態選擇是用dp i 0 表示以i為根節點,不選擇i的最小花費,dp i 1 表示以i為根節點,選擇i的最小花費。但是這樣我發現無法轉移,因為你不能保證選或者不選的正確性 問題在於狀態設少了。乙個點有三種狀況,乙個是本身站有保安,乙個是被自己的子節點控制,乙個未...