行路难,行路难,多歧路,今安在?长风|

hhhqx

园龄:1年8个月粉丝:9关注:14

树上背包优化 - 时间复杂度证明

树上背包优化 - 时间复杂度证明

树上背包

  • 例题
  • 树上背包顾名思义,就是在树上做背包 dp
  • 树上背包的模板代码如下
void dfs(int x){
	sz[x] = 1;
	if(x >= n - m + 1){
		dp[x][1] = -a[x];
		return;
	}
	for(PII e : eg[x]){
		int nxt = e.first;
		dfs(nxt);
		sz[x] += sz[nxt];
		for(int j = m; j >= 0; j--){
			for(int h = 1; h <= j; h++){
				dp[x][j] = min(dp[x][j], dp[x][j - h] + e.second + dp[nxt][h]);
			}
		}
	}
}
  • 但是这样的循环显然是 O(n3)
  • 这有一种固定的优化方法,可以将这三个循环优化到理论 O(n2)

优化

void dfs(int x){
  if(x >= n - m + 1){
    dp[x][1] = -a[x];
    sz[x] = 1;
    return;
  }
  for(PII e : eg[x]){
    int nxt = e.first;
    dfs(nxt);
    for(int j = sz[x]; j >= 0; j--){ // 注意两个循环的范围!
      for(int h = sz[nxt]; h >= 0; h--){
        dp[x][j + h] = min(dp[x][j + h], dp[x][j] + e.second + dp[nxt][h]);
      }
    }
    sz[x] += sz[nxt]; // 注意这里!
  }
}
  • 其实这个优化就是利用子树的背包中有效最大值和有效最小值来优化
  • 证明如下:

时间复杂度证明

感性理解:

  • 可以将 dp 数组的第二维单独看
  • 那么可以转化为一维 dp,显然时间复杂度是 O(n2),因为总共会发生 n2 种转移
  • 如果用 size (大小)来约束枚举的状态,就可以保证没有枚举多余的转移
  • 则第二维总共枚举了 n2 种转移,于是 j 和 h 的循环总共时间复杂度O(n2)

理论证明

就那下面这一份代码来解析。

点击查看代码
void dfs(int x){
  if(x >= n - m + 1){
    dp[x][1] = -a[x];
    sz[x] = 1;
    return;
  }
  for(PII e : eg[x]){
    int nxt = e.first;
    dfs(nxt);
    for(int j = sz[x]; j >= 0; j--){ // 注意两个循环的范围!
      for(int h = sz[nxt]; h >= 0; h--){
        dp[x][j + h] = min(dp[x][j + h], dp[x][j] + e.second + dp[nxt][h]);
      }
    }
    sz[x] += sz[nxt]; // 注意这里!
  }
}

image

本文作者:hhhqx

本文链接:https://www.cnblogs.com/huangqixuan/p/17652214.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   hhhqx  阅读(164)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起