题意
有一棵二叉苹果树,如果数字有分叉,一定是分两叉,即没有只有一个儿子的节点。这棵树共 $N$ 个节点,标号 $1$ 至 $N$,树根编号一定为 $1$。
我们用一根树枝两端连接的节点编号描述一根树枝的位置。一棵有四根树枝的苹果树,因为树枝太多了,需要剪枝。但是一些树枝上长有苹果,给定需要保留的树枝数量,求最多能留住多少苹果。
思路
设$f[i][j]$表示以i为根节点,保留j个节点的最大苹果数量 $$f[i][j]=max{f[l[i]][k]+f[r[i]][j-k-1]+a[i]}(0<=k<=j-1)$$ $$f[i][j]=0(0<i<=n,0<=j<=Q+1)$$ $$f[i][j]=ai$$ $$Answer:f[1][Q+1]$$
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
| #include<bits/stdc++.h> #define ll long long using namespace std; inline ll read(){ char ch=getchar();ll res=0,f=1; while(ch<'0'ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9') res=res*10+ch-'0',ch=getchar(); return res*f; } inline void write(ll x){ if(x<0) putchar('-'),x=-x; if(x<10) putchar(x+'0'); else{ write(x/10); putchar(x%10+'0'); } } ll n,Q,f[110][110],a[110],l[110],r[110],mp[110][110]; void MakeTree(int x){ for(int i=1;i<=n;i++){ if(mp[x][i]!=-1){ l[x]=i;a[i]=mp[x][i]; mp[x][i]=mp[i][x]=-1; MakeTree(i); break; } } for(int i=1;i<=n;i++){ if(mp[x][i]!=-1){ r[x]=i;a[i]=mp[x][i]; mp[x][i]=mp[i][x]=-1; MakeTree(i); break; } } } int DP(int x,int j){
if(j==0){f[x][j]=0;return 0;} if((!l[x])&&(!r[x])){f[x][j]=a[x];return a[x];} if(f[x][j]>0) return f[x][j]; for(int k=0;k<j;k++) f[x][j]=max(f[x][j],DP(l[x],k)+DP(r[x],j-k-1)+a[x]); return f[x][j]; } int main(){ n=read();Q=read();Q++; memset(mp,-1,sizeof(mp)); for(int i=1;i<=n-1;i++){ int x=read(),y=read(),z=read(); mp[y][x]=mp[x][y]=z; } MakeTree(1); write(DP(1,Q));putchar('\n');
return 0; }
|