樹形dp瞎講+樹形dp基礎題題解
---恢復內容開始---
沒錯
咕了這麼久(沒有青青姐久
我又開始寫部落格了( ´▽`)
想了很久些什麼(才沒有想過呢
雖然被鄙視基礎不好但還是走上了樹形dp的不歸路
那麼
就來寫寫樹形dp吧(dtx daolao不要打我
樹形dp是什麼呢?
一言概之,dfs中的動態規劃
emmmmm
對
因為沒什麼固定格式
就推轉移方程(所以我一開始根本找不到講樹形dp的blog
然後發現了良心部落格一枚
基本的dp方程
選擇節點類
dp[i][0]=dp[j][1]dp[i][1]=max/min(dp[j][0],dp[j][1]){dp[i][0]=dp[j][1]dp[i][1]=max/min(dp[j][0],dp[j][1])樹形揹包類
dp[v][k]=dp[u][k]+val
雖然關於樹形dp的部落格基本上都是題
但是看懂了基本dp方程,理解了實質大概就不會特別難(我這句話真嚴謹
然後
題還是有很多的
就不放題面了
放連結好了
(要是放一堆圖片有假裝寫了很多的嫌疑
核心的程式碼就是上邊放的狀態轉移方程
#include<cstdio> #include<algorithm> using namespace std; #define maxn 6010 intfa[maxn],dp[maxn][2]; int root,n; int v[maxn]; int nxt[maxn],head[maxn]; void treedp(int x){ for(int i = head[x];i;i = nxt[i]){ treedp(i); dp[x][0] += max(dp[i][1],dp[i][0]);//dp[x][0]代表上司x不來時的最大快樂指數 dp[x][1] += dp[i][0];//dp[x][1]代表上司來的 } } int main() { scanf("%d",&n); for(int i = 1; i <= n; i++) scanf("%d",&dp[i][1]); for(int i = 1; i < n; i++) { int x,y; scanf("%d%d",&x,&y); v[x] ++;//記錄一下有沒有上司 nxt[x] = head[y]; head[y] = x;//對,像鏈式前向星的東西(我還理解了好久【劃掉 } for(int i = 1; i <= n; i++) if(!v[i]) {//沒有上司的就是最大上司啦 root = i; break; } treedp(root);//從樹根開始dp printf("%d",max(dp[root][0],dp[root][1]));//取最高上司來和不來的最大快樂指數 return 0; }
emmmmm
還是蠻好懂的吧
然後上下一道
這裡有一點點的變化
就是剪掉了之後是加0
#include<cstdio> #include<algorithm> using namespace std; #define maxn 16010 int dp[maxn]; int cnt,head[maxn * 2]; int f[maxn];//記錄當前子節點到之下的花的最大值 int ans = -2147483647;//因為可能全是負的所以ans搞到最小 struct EDGE{ int nxt,to; }edge[maxn * 2]; void add(int x,int y){ edge[++cnt].to = y; edge[cnt].nxt = head[x]; head[x] = cnt; }//正常的加邊看上去真舒服啊 void treedp(int u,int fa){ f[u] = dp[u];//給f[u]賦值為它本身的大小 for(int i = head[u];i;i = edge[i].nxt){ int v = edge[i].to;//v是u的兒子 if(v != fa){//唔防止雙向加邊跑回去 treedp(v,u); f[u] += max(0,f[v]); } } ans = max(ans,f[u]);//反正所有的花都在一根上不需要加和什麼的(我在說什麼廢話 } int main(){ int n; scanf("%d",&n); for(int i = 1;i <= n;i++) scanf("%d",&dp[i]); for(int i = 1;i < n;i++){ int x,y; scanf("%d%d",&x,&y); add(x,y); add(y,x); } treedp(1,0);//將1的父節點定義為0 printf("%d",ans); return 0; }
唔嗷【好睏
(明天的聯歡是我寫部落格的動力【不小心暴露了什麼
下一道來
(嚇死我了插連結的時候突然閃退了(╥﹏╥)還好有自動儲存這種可愛的東西
emmmm
這道題似乎又回到了原點?
其實跟沒有上司的舞會很像
就是上司不來,下屬必須來
上司來,下屬來不來都行
(有點像開會?總得來一個負責人,當然都希望來的越少越好了【因為懶
#include<cstdio> #include<algorithm> using namespace std; #define maxn 1510 struct EDGE{ int nxt,to; }edge[maxn]; int cnt,head[maxn]; int v[maxn]; int dp[maxn][2]; void add(int x,int y){ edge[++cnt].to = y; edge[cnt].nxt = head[x]; head[x] = cnt; } void treedp(int x){ dp[x][1] = 1;//放的地方都是一 for(int i = head[x];i;i = edge[i].nxt){ int u = edge[i].to; treedp(u); dp[x][0] += dp[u][1];//當前點不放,下一個點一定要放 dp[x][1] += min(dp[u][1],dp[u][0]);當前放了下一個點不一定放不放 } } int main(){ int n; scanf("%d",&n); for(int i = 0;i < n;i++){ int r,k; scanf("%d%d",&r,&k); for(int j = 0;j < k;j++){ int p; scanf("%d",&p); v[p]++; add(r,p); } } int root; for(int i = 0;i < n;i++) if(!v[i]){ root = i; break; }//唔又是找根 treedp(root); printf("%d",min(dp[root][0],dp[root][1])); return 0; }
啊友情提示
a掉這道題之後可以順道a掉luogu UVA1292 Strategic game
差別就是這道題要輸入多組資料而已
/*
emmmmm
去寫選課
寫完就發
*/
好的我鴿了
告辭【快速溜