動態規劃 樹型DP
codves5565 二叉蘋果樹
時間限制: 1 s 空間限制: 128000 KB 題目描述 Description
有一棵蘋果樹,如果樹枝有分叉,一定是分2叉(就是說沒有只有1個兒子的結點)這棵樹共有N個結點(葉子點或者樹枝分叉點),編號為1-N,樹根編號一定是1。我們用一根樹枝兩端連接的結點的編號來描述一根樹枝的位置。現在這顆樹枝條太多了,需要剪枝。但是一些樹枝上長有蘋果。
給定需要保留的樹枝數量,求出最多能留住多少蘋果。
輸入描述 Input Description
第1行2個數,N和Q(1<=Q<= N,1<N<=100)。
N表示樹的結點數,Q表示要保留的樹枝數量。接下來N-1行描述樹枝的信息。
每行3個整數,前兩個是它連接的結點的編號。第3個數是這根樹枝上蘋果的數量。
每根樹枝上的蘋果不超過30000個。
輸出描述 Output Description
剩余蘋果的最大數量。
樣例輸入 Sample Input
5 2
1 3 1
1 4 10
2 3 20
3 5 20
樣例輸出 Sample Output
21
數據範圍及提示 Data Size & Hint
對於20%數據 n<=20;
對於100%數據1<N<=100,1<=Q<= N.
#include<cstdio> #include<algorithm> #include<cstring> usingView Codenamespace std; struct node { int l,r,c; }map[2001]; int f[1005][1005]; int n,q,maxx=0; void dfs(int i,int j) { int k; if(j==0) f[i][j]=0; else if(map[i].r==0&&map[i].l==0) f[i][j]=map[i].c; else { f[i][j]=0; for(k=0;k<j;k++) { if(f[map[i].l][k]==0) dfs(map[i].l,k); if(f[map[i].r][j-k-1]==0) dfs(map[i].r,j-k-1); f[i][j]=max(f[i][j],f[map[i].l][k]+f[map[i].r][j-k-1]+map[i].c); // maxx=max(maxx,f[i][j]); //printf("%d ",maxx); } } } int main() { scanf("%d %d",&n,&q); int v,u,c; for(int i=1;i<n;i++) { int p=0; scanf("%d %d %d",&v,&u,&c); for(int j=1;j<=n;j++) if(map[j].l==u||map[j].r==u) p=1; if(p==0) { if(map[v].l==0) map[v].l=u; else if(map[v].r==0) map[v].r=u; map[u].c=c; } else { if(map[u].l==0) map[u].l=v; else if(map[u].r==0) map[u].r=v; map[v].c=c; } } //for(int i=1;i<=n;i++) printf("%d %d %d\n",map[i].l,map[i].r,map[i].c); dfs(1,q+1); //for(int i=1;i<=n;i++) printf("%d ",map[i]); printf("%d",f[1][q+1]); }
初始化:f[i][0]=0,f[i][1]=map[i];
轉移方程:f[i][j]=max(f[i][j],f[map[i].l][k]+f[map[i].r][j-k-1]+map[i].c);
謝謝姚老教導;
接下來膜ccz大爺 附代碼 很強勢;
#include<bits/stdc++.h> struct edge{ int to,v; }; int n,q; std::vector<edge>e[107]; int f[107][107],sz[107],v[107]; void maxs(int&a,int b){if(a<b)a=b;} void f1(int w,int pa){ sz[w]=1; f[w][1]=v[w]; for(int i=0;i<e[w].size();++i){ int u=e[w][i].to; if(u==pa)continue; v[u]=e[w][i].v; f1(u,w); for(int k=sz[w];k>=1;--k) for(int j=1;j<=sz[u];++j){ maxs(f[w][k+j],f[w][k]+f[u][j]); } sz[w]+=sz[u]; } } int main(){ scanf("%d%d",&n,&q); for(int i=1,a,b,c;i<n;++i){ scanf("%d%d%d",&a,&b,&c); e[a].push_back((edge){b,c}); e[b].push_back((edge){a,c}); } f1(1,0); printf("%d\n",f[1][q+1]); return 0; }View Code
------------------------
codves1380 沒有上司的舞會
時間限制: 1 s 空間限制: 128000 KB 題目描述 Description
Ural大學有N個職員,編號為1~N。他們有從屬關系,也就是說他們的關系就像一棵以校長為根的樹,父結點就是子結點的直接上司。每個職員有一個快樂指數。現在有個周年慶宴會,要求與會職員的快樂指數最大。但是,沒有職員願和直接上司一起與會。
輸入描述 Input Description第一行一個整數N。(1<=N<=6000)
接下來N行,第i+1行表示i號職員的快樂指數Ri。(-128<=Ri<=127)
接下來N-1行,每行輸入一對整數L,K。表示K是L的直接上司。
最後一行輸入0,0。
輸出最大的快樂指數。
樣例輸入 Sample Input7
1
1
1
1
1
1
1
1 3
2 3
6 4
7 4
4 5
3 5
0 0
5
數據範圍及提示 Data Size & Hint各個測試點1s
#include<cstdio> #include<algorithm> #include<cstring> #define long long ll using namespace std; const int N=6010; int map[N]; struct node { int to,next; }e[N*2]; int boss[N]={0}; int first[N],cnt=0; int is_boss; int f[N][5]; void insert(int v,int u) { e[++cnt].to=u;e[cnt].next=first[v];first[v]=cnt; //printf("===========\n%d %d %d\n==========\n",e[cnt].to,e[cnt].next,first[cnt]); } void dfs(int x) { f[x][0]=0;f[x][1]=map[x]; for(int i=first[x];i;i=e[i].next) { int p=e[i].to; dfs(p); f[x][0]+=max(f[p][0],f[p][1]); f[x][1]+=f[p][0]; //printf("%d %d\n",f[x][0],f[x][1]); } } int main() { int n; scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&map[i]); int v,u; while(1) { scanf("%d %d",&v,&u); if(v+u==0) break; boss[v]++; insert(u,v); } //printf("-------------------------\n"); for(int i=1;i<=n;i++) if(!boss[i]) {is_boss=i;break;} //printf("%d \n",is_boss); dfs(is_boss); printf("%d",max(f[is_boss][1],f[is_boss][0])); return 0; }View Code
轉移方程:
f[]中的0代表不選,1代表選;
謝謝姚老教導(again);
-----------------------------------------
動態規劃 樹型DP