poj 2152 fire
題意:
給乙個n
個節點和n−
1條邊的樹,邊權代表距離,要在這些點中選擇一些點建立消防站,使得每個點都會被消防站覆蓋到。每個點有兩個屬性:co
st[i
] 表示在這個點建立消防站的代價,li
mit[
i]表示當某個消防站離
i 的距離不超過li
mit[
i]時,這個點就可以認為被該消防站覆蓋,求使得
n 個點都被消防站覆蓋的最小代價?
資料範圍:n≤
103,邊
權≤103
,cos
t[i]
≤104,
limt
[i]≤
104分析:
點依賴型樹形dp
。 首先對每個點df
s 一遍可以得到每個點到其餘點的距離,時間複雜度:o(
n2) 。
然後遞迴解決以
u 為根的子樹, 需要記錄或者說列舉
u被那個消防站覆蓋,用dp
[u][
i]表示
u 被在點
i上建立的消防站覆蓋時以
u 為根的子樹都被消防站覆蓋的最優解。顯然首先需要滿足di
s[u]
[i]≤
limi
t[u]
。考慮狀態轉移,對於
u 的每個兒子
v,這時我們還需要知道解決以
v 為根的子樹時的最優解be
st[v
],be
st[v
] 包含了
v 也被覆蓋的最小代價。
v選擇的覆蓋它的消防站有兩種可能:是
i 或者不是
i,所以有: dp
[u][
i]+=
min(
dp[v
][i]
−cos
t[i]
,bes
t[v]
) 更新b
est[
] :be
st[u
]=mi
n(be
st[u
],dp
[u][
i])
總的時間複雜度:o(
n2) 。
陳啟峰的」一張一弛,解題之道」**
#include
#include
#include
#include
using
namespace
std;
typedef
long
long ll;
const
int max_n = 1010;
const
int inf = 0x3f3f3f3f;
int t, n, total;
int head[max_n], cost[max_n], limit[max_n], dis[max_n][max_n];
int dp[max_n][max_n], best[max_n];
struct edge edge[max_n * 2];
void addedge(int u, int v, int w)
void dfs_dis(int u, int p, int root)
}void wyr(int u, int p)
for (int i = 1; i <= n; ++i)
best[u] = min(best[u], dp[u][i]);
//printf("i = %d best[%d] = %d dp[%d][%d] = %d\n", i, u, best[u], u, i, dp[u][i]);
}}int main()
for (int i = 1; i <= n; ++i)
total = 0;
memset(head, -1, sizeof(head));
for (int i = 1; i < n; ++i)
memset(dis, 0, sizeof(dis));
for (int i = 1; i <= n; ++i)
memset(best, 0x3f, sizeof(best));
memset(dp, 0x3f, sizeof(dp));
wyr(1, 0);
printf("%d\n", best[1]);
}return
0;}
POJ 2152 樹形DP 暴力列舉
題目鏈結 題意 給一顆樹可以在樹上的節點上建立消防站費用為w i 如果不建消防站需要在距離該節點距離小於等於d i 的地方有消防站,求使得整顆樹被覆蓋的最小費用。思路 定義ans陣列 ans u 表示以u為根的子樹的答案 定義dp陣列 dp u v 表示節點u被建立在節點v的消防站覆蓋的最小答案 定...
POJ2152 消防站解題報告
做這道題的時候,我一開始狀態設計的太緊了,我設f i 表示以i為根的子樹自己搞定自己需要的最小代價,然後我列舉控制根的點。然後發現轉移是o n 3 的。看了 之後發現其實改變一下狀態就可以了,其實顯然的一件事就是我們現在是在列舉兩個點之間的關係了,那麼我們不妨設f i,j 為j控制i,且以i為根的子...
poj 2152 一道很難的樹型DP
題目 poj 2152 fire 我想說的 以前做揹包的題目做多了,腦子形成了一種就是所有動態規劃就是在陣列上進行等一些固定的思想。結果最近在做一些題目的時候,感覺無從下手,想好久都沒結果。非常慶幸自己做了這類題目,讓我從那種狹隘的思想中做出來。以後就要根據實際情況研究狀態了。題意 有n個城市,每兩...