先对多叉树转成二叉树,便于DP.
题目给出了第一个点必须吃的果子个数,和最多有几个头,那么如果头的个数 m>2,交替着吃肯定是最优的,
如果 =2,那么就不好说了,我们对节点进行染色,将"大头"吃的染成色 0,其他头吃的染成色 1,那么对于
m>2的情况,一条边的两端都被染成 1,那么不需要增加"难受值",只增加两端色为 0的边,如果 m=2,那么只
要两端染成相同色就得增加"难受值".
状态转移方程为:
f[i,j,p]=min{f[lc[i],k,0]+w[i],f[lc[i],k-1,1]+w[i]*ord(m=2)}+f[rc[i],j-k,p]
边界条件:f[i,j,p]=INF(j<0),f[0,0,p]=0.目标状态:f[lc[1],tot-1,0].
核心代码:
procedure dfs(x:longint); {小优化,搜个数}
begin
if x=0 then exit; {边界}
a[x]:=1;
dfs(tree[x].lc);
dfs(tree[x].rc);
a[x]:=a[x]+a[tree[x].lc]+a[tree[x].rc];
end;
procedure init;
var
i,x,y,d:longint;
begin
fillchar(tree,sizeof(tree),0);
readln(n,m,p);
for i:=1 to n-1 do
begin
readln(x,y,d);
tree[y].rc:=tree[x].lc; {树转二叉树}
tree[x].lc:=y;
tree[y].data:=d;
end;
fillchar(a,sizeof(a),0);
dfs(1);
end;
function dp(x,k,la:longint):longint;
var
i,l,r,temp:longint;
begin
if k<0 then exit(INF); {边界}
if (x=0)and(k=0) then
begin
f[x,k,la]:=0;
exit(0);
end;
if f[x,k,la]<>-1 then
exit(f[x,k,la]);
f[x,k,la]:=INF;
for i:=0 to min(k,a[x]) do
begin
l:=dp(tree[x].lc,i-1,0)+(ord(la=0)*tree[x].data);
{决策1}
r:=dp(tree[x].lc,i,1)+(ord(la=1)*ord(m=2)*tree[x].data); {决策2}
temp:=min(l,r)+dp(tree[x].rc,k-i,la);
f[x,k,la]:=min(f[x,k,la],temp);
end;
exit(f[x,k,la]);
end;