洛谷 P1352 沒有上司的舞會 解題報告 樹形DP
阿新 • • 發佈:2018-07-22
最值 周年慶 include -a void pre 代碼 style 結果
題目描述
某大學有N個職員,編號為1~N。他們之間有從屬關系,也就是說他們的關系就像一棵以校長為根的樹,父結點就是子結點的直接上司。現在有個周年慶宴會,宴會每邀請來一個職員都會增加一定的快樂指數Ri,但是呢,如果某個職員的上司來參加舞會了,那麽這個職員就無論如何也不肯來參加舞會了。所以,請你編程計算,邀請哪些職員可以使快樂指數最大,求最大的快樂指數。
輸入輸出格式
輸入格式:
第一行一個整數N。(1<=N<=6000)
接下來N行,第i+1行表示i號職員的快樂指數Ri。(-128<=Ri<=127)
接下來N-1行,每行輸入一對整數L,K。表示K是L的直接上司。
最後一行輸入0 0
輸出格式:
輸出最大的快樂指數。
輸入輸出樣例
輸入樣例#1: 復制7 1 1 1 1 1 1 1 1 3 2 3 6 4 7 4 4 5 3 5 0 0輸出樣例#1: 復制
5題目已經強烈暗示了這題怎麽做,結構為樹,對每個人又要處理兩個抉擇,毫無疑問是爆搜(劃掉),樹形DP啦
先介紹一手樹形DP
簡單來說,樹形DP就是一個找兒子的DP,所有父親節點的狀態都由兒子更新,以此題為例,對於每個有下屬的人來說都有兩個選擇,自己不去,自己的下屬愛去不去;自己去,自己的下屬想去也不行,那麽轉移方程就出來了
設f[i][0/1]表示第i個人不去/去時的最大快樂值
f[i][0]=max(f[son][0],f[son][1])//下屬去不去中的最值
f[i][1]=max(f[son][0])+happy[i]//下屬想去也不行+自己的快樂值(這是下屬去不了自己就很快樂嗎。。。)
下面結合代碼講下
完整代碼
#include<bits/stdc++.h> using namespace std; const int MAXN=6005; vector<int>son[MAXN]; int f[MAXN][2],a[MAXN],rt,n; bool vis[MAXN]; void dfs(int rt) { f[rt][0]=0;//不去的話不加上自己的快樂值 f[rt][1]=a[rt];//去的話加上自己的快樂值 for(int i=0;i<son[rt].size();i++)//找呀找呀找兒子 { int y=son[rt][i];//找到一個兒子 dfs(y);//遞歸向下,樹形DP是一個整合的過程,一切都是從最底層向上走的 f[rt][0]+=max(f[y][0],f[y][1]);//如果是第一次走到這一步說明已經到了底,之後每一次到說明到在一層一層往上走,套方程更新不去 f[rt][1]+=f[y][0];//套方程更新去的最大值 } } int main() { cin>>n; for(int i=1;i<=n;i++) cin>>a[i];//讀入快樂值 for(int i=1;i<=n;i++) { int x,y; cin>>x>>y; son[y].push_back(x);//讀入並連好父親到兒子的邊 vis[x]=1;//標記兒子 } for(int i=1;i<=n;i++)//找到沒有被標記的人,他就是校長,也就是總的根節點 if(!vis[i]) { rt=i;break; } dfs(rt);//從根節點開始DP cout<<max(f[rt][0],f[rt][1]); //所有的結果都會匯總到根節點中,輸出他去還是不去的最值即可 return 0; }
洛谷 P1352 沒有上司的舞會 解題報告 樹形DP