POJ 2152 樹形DP 暴力列舉

2021-08-20 15:39:12 字數 1270 閱讀 6587

題目鏈結

題意:給一顆樹可以在樹上的節點上建立消防站費用為w[i],如果不建消防站需要在距離該節點距離小於等於d[i]的地方有消防站,求使得整顆樹被覆蓋的最小費用。

思路:定義ans陣列:ans[u]表示以u為根的子樹的答案

定義dp陣列:dp[u][v]表示節點u被建立在節點v的消防站覆蓋的最小答案

定義dis陣列:dis[u][v]表示u,v兩點之間的距離

此題資料較小為1000比正常的樹形dp題的資料差乙個平方,所以在一些處理上可以考慮列舉

對於dp[u][v]的計算:

當dis[u][v]>d[u]時,dp[u][v]=inf 反之

dis[u][v] = w[v] + σ min( ans[son] ,  dp[son][v]-w[v] )

dp[son][v]-w[v]可以看成是否可以更加優化答案

ans[u] = min( dp[u][1] , ... , dp[u][n] )

c++**:

#include#include#include#include#include#include#include#include#include#include#includeusing namespace std;

const int maxn = 1010;

const int maxm = 2010;

const int inf = 0x3f3f3f3f;

int n,tol,head[maxn],w[maxn],d[maxn];

struct edge

es[maxm];

void addedge( int u , int v , int w )

int ans[maxn],dp[maxn][maxn],dis[maxn][maxn];

void cal_dis( int s , int u , int f , int d )

void dfs( int u , int f )

}dp[u][v] += w[v];}}

for ( int i=1 ; i<=n ; i++ )

ans[u] = min( ans[u] , dp[u][i] );

}int main()

for ( int i=1 ; i<=n ; i++ )

cal_dis( i , i , 0 , 0 );

dfs( 1 , 0 );

printf ( "%d\n" , ans[1] );

}return 0;

}

poj 2152 一道很難的樹型DP

題目 poj 2152 fire 我想說的 以前做揹包的題目做多了,腦子形成了一種就是所有動態規劃就是在陣列上進行等一些固定的思想。結果最近在做一些題目的時候,感覺無從下手,想好久都沒結果。非常慶幸自己做了這類題目,讓我從那種狹隘的思想中做出來。以後就要根據實際情況研究狀態了。題意 有n個城市,每兩...

POJ 2152 Fire(依賴型樹形dp)

poj 2152 fire 題意 給乙個n 個節點和n 1條邊的樹,邊權代表距離,要在這些點中選擇一些點建立消防站,使得每個點都會被消防站覆蓋到。每個點有兩個屬性 co st i 表示在這個點建立消防站的代價,li mit i 表示當某個消防站離 i 的距離不超過li mit i 時,這個點就可以認...

POJ2152 消防站解題報告

做這道題的時候,我一開始狀態設計的太緊了,我設f i 表示以i為根的子樹自己搞定自己需要的最小代價,然後我列舉控制根的點。然後發現轉移是o n 3 的。看了 之後發現其實改變一下狀態就可以了,其實顯然的一件事就是我們現在是在列舉兩個點之間的關係了,那麼我們不妨設f i,j 為j控制i,且以i為根的子...