POJ 1155 樹形DP 揹包 優化

2021-09-08 10:29:25 字數 1441 閱讀 4660

題目鏈結

題目大意:電視台轉播節目。對於每個根,其子結點可能是使用者,也可能是中轉站。但是使用者肯定是葉子結點。傳到中轉站或是使用者都要花錢,如果是使用者,則還可以收錢。問在不虧本的前提下最多能有多少個使用者看到節目。

解題思路

比較麻煩的樹形揹包。首先cost=1。

花的錢權在邊,收的錢權在點,且是葉子結點。所以首先可以對葉子結點進行預處理。

用dp[i][j]表示在i點時傳播j個使用者(包含自身),則dp[n-m-1~n][1]=每個使用者繳費。

這樣在dfs的時候就可以專心處理邊權問題。兩個for迴圈這麼寫:

for(f...j...cost)

for(0...k...j)

則轉移方程就是dp[i][j]=max(dp[i][j],dp[i][j-k]+dp[t][k]-e[a].w);

這裡之所以是f而不是f+1,是因為中轉站不是使用者,不需要cost。f+=dfs(t)。

對於如何知道在不虧本的情況下的最多使用者,在dfs之後,從dp[1][m..0]開始找乙個大於0的最大m值。

如果你熟悉傳統的樹形揹包的話,就會發現這裡不能每次都使用最大揹包容量m迴圈了,不然會tle,原因是這題m比較大,每次都從m開始不t就怪了。

所以必須採用這種cost=1時特殊的當前最大容量f。

#include "

cstdio

"#include

"iostream

"#include

"cstring

"using

namespace

std;

#define maxn 3005

#define inf 0x3f3f3f3f

struct

edge

e[maxn];

int leaf[maxn],dp[maxn][maxn],get

[maxn],head[maxn];

intn,m,k,v,w,tol;

void addedge(int u,int v,int

w)int dfs(int

root)

returnf;}

intmain()

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

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

dp[i][j]=-inf;

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

dfs(1);

for(int i=m;i>=0;i--)

}}

13540208

neopenx

1155

accepted

33704k

157ms

c++1322b

2014-10-18 00:48:42

POJ 1155 TELE (樹形DP,樹形揹包)

題意 給定一棵樹,n個節點,其中有m個葉子表示的是使用者,其他點表示中轉器,每條邊都有權值,每個使用者i願意給的錢w i 問如果在不虧錢的情況下能為多少使用者轉播足球比賽?思路 其實就是要選出部分葉子節點,其花費 所選葉子權值 經過的所有邊權 每條邊只算1次花費 那麼對於每個節點,可以考慮在其子樹下...

poj1155 TELE(樹形 揹包dp)

題意 某電台要廣播一場比賽,該電台網路是由n個網點組成的一棵樹,其中m個點為客戶端,其餘點為 站。客戶端i願支付的錢為pay i 每一條邊需要的花費固定,問電台在保證不虧損的情況下,最多能使多少個客戶端接收到資訊?思路 設dp i j 表示i節點為根節點並且子樹已經有j個使用者的時候最大剩餘費用。那...

POJ 1155 TELE 樹形揹包

1為根節點,有m個葉節點,其他為中間結點,每個結點的權值代表他願意付出的錢,邊的權值代表聯通兩節點的代價,求不虧損的情況下最多能到達多少個葉節點。另dp u i 表示根節點為u的子樹此時裝了i個葉節點的盈利情況 m oney i e dgec osti 那麼我們就能得到這樣的狀態轉移方程 如果u是葉...