日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

树形DP入门题目推荐以及解析

發布時間:2025/4/16 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 树形DP入门题目推荐以及解析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

關于樹形DP幾道入門題目

今天惡補樹形DP,感覺海星。
其實挺簡單的。
介紹幾道例題,我會的。
1.洛谷P1352 沒有上司的舞會
我的一篇題解
我們可以考慮每一個節點都是有兩種情況。
一個是被邀請;另一個是不會被邀請。
前者后果就是子節點不可以被選擇;
后者結果就是子節點可以被選擇。
于是關系明確,狀態轉移方程為:
dp[root][0] += std::max(dp[son[root][i]][0],dp[son[root][i]][1]);
dp[root][1] += dp[son[root][i]][0];
海星。
son[root][i]是當前節點的兒子。
初始化要記得是每一個點的快樂指數。

#include <cstdio> #include <iostream> #include <cmath> #include <cstring> #include <algorithm> #include <queue> #include <stack> #include <vector> #define Max 6050 #define re register std::vector<int>son[Max]; int n,root,dp[Max][2],fa[Max]; void dfs(int root) {for(re int i = 0 ; i < son[root].size() ; ++ i)dfs(son[root][i]);for(re int i = 0 ; i < son[root].size() ; ++ i) {dp[root][0] += std::max(dp[son[root][i]][0],dp[son[root][i]][1]);dp[root][1] += dp[son[root][i]][0];} } void init() {scanf("%d",&n);int u,v;memset(fa,-1,sizeof fa);for(re int i = 1 ; i <= n ; ++ i) scanf("%d",&dp[i][1]);for(re int i = 1 ; i < n ; ++ i)scanf("%d%d",&u,&v),fa[u]=v,son[v].push_back(u);scanf("%d%d",&u,&v); } inline void print(int root) {printf("%d",std::max(dp[root][0],dp[root][1]));} void work() {int root=1;while(fa[root] != -1) root = fa[root];dfs(root);print(root); } int main() {init();work();return 0; }

2.poj1463 Strategic game
我們考慮每一個節點有兩種情況。
一個是被選擇;另一個是不被選擇。
前者的結果是他的子節點可以被選擇,也可以不被選擇;
后者的結果是他的子節點必須備選擇。
所以狀態轉移方程出來了:
dp[root][0] += std::max(dp[son[root][i]][0],dp[son[root][i]][1]);
dp[root][1] += dp[son[root][i]][0];

#include <cstdio> #include <iostream> #include <cmath> #include <cstring> #include <algorithm> #include <queue> #include <stack> #include <vector> #define Max 1550 #define re register int n,dp[Max][2],fa[Max]; std::vector<int>son[Max]; void dfs(int root) {for(re int i = 0 ; i < son[root].size() ; ++ i)dfs(son[root][i]);for(re int i = 0 ; i < son[root].size() ; ++ i) {dp[root][0] += dp[son[root][i]][1];dp[root][1] += std::min(dp[son[root][i]][0],dp[son[root][i]][1]);} } void print(int root) {printf("%d\n",std::min(dp[root][0],dp[root][1]));} void work() {int root=0;while(fa[root] != -1) root = fa[root];dfs(root);print(root); } void init() {int k,x,y;char ch;while(scanf("%d",&n) != EOF) {for(re int i = 0 ; i < n ; ++ i)fa[i] = -1,dp[i][0] = 0,dp[i][1] = 1;for(re int p = 1 ; p <= n ; ++ p) {scanf("%d",&k);std::cin >> ch;std::cin >> ch;scanf("%d",&y);std::cin >> ch;son[k].clear();for(re int i = 1 ; i <= y ; ++ i)scanf("%d",&x),fa[x]=k,son[k].push_back(x);}work();} } int main() {init();return 0; }

轉載于:https://www.cnblogs.com/handsomegodzilla/p/11360573.html

總結

以上是生活随笔為你收集整理的树形DP入门题目推荐以及解析的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。