概述
樹形dp是dp的一種,有時候會和區間dp結合。
由於樹有著天然的遞迴結構 父子結構 而且它作為一種特殊的圖 可以描述許多複雜的資訊 因此在樹就成了一種很適合dp的框架一般實現:問題:給你一棵樹 要求用最少的代價(最大的收益)完成給定的操作
樹形dp 一般來說都是從葉子從而推出根 當然 從根推葉子的情況也有 不過很少
一般實現方式: dfs(包括記憶化搜尋) 遞推等
void dfs(int rot)
}
題目
洛谷p1040
這個題不僅是樹形dp(主要是遍歷),還是個區間dp,一般題目給出樹的中序遍歷,都是區間dp+樹形dp。
中序遍歷一般都是通過列舉l,r區間的根來進行區間dp的。
**:(這個是很久以前寫的,比較醜)
#include using namespace std;
const int n = 37;
int n,a[n],m[n][n],root[n][n];
//遍歷整個樹
int dfs(int i, int j)
} return m[i][j] = ans;
}//前序遍歷輸出根
int prt(int l,int r)
printf("%d ",root[l][r]);
prt(l , root[l][r]-1);
prt(root[l][r]+1 , r);
}int main()
洛谷p1122 最大子樹和
看題目,非常模板的樹形dp,注意因為不一定選的是包含根節點的一段,所以答案不在根節點上,每次要max更新ans。
**:
#include using namespace std;
const int n = 16007;
int n,a[n],f[n],ans;
bool vis[n];
vector g[n];
void dfs(int x)
}int main()
dfs(1);
printf("%d\n",ans);
return 0;
}
洛谷p1352 沒有上司的舞會
也是很模板的樹形dp,不過轉移方程要想一下,如果上司選了,下司一定不能選,如果上司沒選,下司可以選也可以不選。
**:(也是很久之前寫的了,略醜)
#include using namespace std;
const int n = 6e3 + 7;
int n;
int f[n][2];
struct ed
edge[n];
int dfs(int root)
}int main()
int t1,t2,rt;
scanf("%d %d",&t1,&t2);
for(int i = 1; i <= n; i++)
f[i][1] = edge[i].w;
//找rot dp起點
for(int i = 1; i <= n; i++)
if(!edge[i].fa) rt = i;
dfs(rt);
printf("%d\n",max(f[rt][1],f[rt][0]));
return 0;
}
三道題,不同年**的,寫了三種存樹的方式,我也是佩服我自己。
未完待續
2023年8月4日
樹形dp總結
from 列出一些經典問題吧 1 給出一棵樹 每個節點有權值 要求父節點和子節點不能同時取 求能夠取得的最大值 hdu1520 2 給出一棵樹,求離每個節點最遠的點的距離 hdu2196 3 1 在乙個地圖上,有n座城堡,每座城堡都有一定的寶物,在每次遊戲中允許攻克m個城堡並獲得裡面的寶物。但由於地...
樹形dp總結
這個月一直搞dp了,狀壓,數字,樹形,感覺雖然有時訓練很辛苦,但真的很充實。這個星期看了一些樹形dp的資料。樹形dp簡單來說就是在樹上的dp,這裡的很多題,都和揹包有聯絡,從乙個根節點開始,分配方案給它的子樹。有乙個很有意思的題。沒有上司的聚會 hdu 1520 大致題意就是說,要舉辦乙個聚會,每個...
樹形DP總結
換根 fat結點更新u結點子結點 dp fat ans fat max dp u 0 老方法 更新根節點 ans u dp u max dp fat 0 第一次dfs 回溯時處理子結點為u向下的簡單路徑第一大和第二大 第二次dfs 遞迴處理子結點為u向上的簡單路徑最大 const int n 5e5...