题目
思路
整道题看起来有很多要点要考虑
最先想出的DP方程
dp[i][j]表示第i个结点所在子树建j个伐木场的最小花费
dp[i][j] = min(dp[v][k] + cost)
看起来挺好的,时间复杂度也不高,但问题来了
cost怎么算啊
不知道剩余木材 不知道走的距离
于是老师说 要三维 \color{red}\text{要三维} 要三维
定义dp[i][j][k]表示第i个结点所在子树建j个伐木场且最近的一个伐木场在k
然后我 没有想出来 \color{blue}\text{没有想出来} 没有想出来
于是去看了洛谷题解,但觉得讲的不是很清楚,特于此再写一篇
定义四维的
dp[i][j][k]表示第i个结点最近且建了伐木场的为j 共建k个的最小花费 1 表示在i点建了
注意 上面的最近伐木场指的是祖先结点上的
记录祖先 考虑用
ancestor[++tot] = x;放在dfs里的首行
tot--;放在末行
非常好理解
记录距离和木材数
只要知道应前往之地和现在所在之地 就可以用这种方式表示
u:现在所在之地
v:应前往之地
dep[i]记录i到根1的距离
即dis(u,v) = |dep[v] - dep[u]|
木材数则从这里一次性运到伐木场,所以不记录中间状态
wood[i]表示i点的木材
然后就是最重要的状态转移方程了
dp[x][fa][k][0] = Min(dp[x][fa][k][0],dp[v][fa][l][0] + dp[x][fa][k - l][0]);
dp[x][fa][k][1] = Min(dp[x][fa][k][1],dp[v][x][l][0] + dp[x][fa][k - l][1]);
然后就有非常讲究的事儿了
for(j = 1;j <= tot;j++)
{
//j的顺序无所谓
int fa = ancestor[j];
for(k = maxk;k >=