生活随笔
收集整理的這篇文章主要介紹了
树形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入门题目推荐以及解析的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。