zoukankan      html  css  js  c++  java
  • 背包类树形DP-洛谷P2014 [CTSC1997]选课


    注:本文章参考《算法竞赛 进阶指南》(李煜东2018年1月第一版P291~292),引用文本均摘自该书

    背包类树形DP

    又称树形有依赖的背包问题。实际上是背包和树形DP结合。除了以“节点编号”作为树形DP的阶段,通常我们也像线性DP一样,吧当前背包的“体积”作为第二维状态。在状态转移时,我们要处理的实际上就是一个分组背包问题。
    另外,还可以按照“左儿子右兄弟”的方法,把多叉树转化为二叉树,再进行计算

    例题

    链接:https://www.luogu.com.cn/problem/P2014
    在这里插入图片描述

    思路

    1. 设置一个0号结点,并将其作为 所有k=0的节点 的父节点,从而将森林转化为树
    2. 设f[x][t]表示以x为根的子树中选t门课能够获得的最高分,显然,f[x][0]=0
    3. 进一步推状态转移方程:设节点x的某个子节点为y,那么显然f[x][t]可以由f[y][ ]推导而来:t个节点中可能存在a(a∈[1,t])个节点在以y为根的子树上,即f[x][t]=max(f[x][t] , f[x][t-a]+f[y][a])。所以,状态转移:
    			for(int j = t ; j >= 0 ; j--)
    				if(t - j >= 0)
    					if(f[x][t] < f[x][t - j] + f[y][j])
    						f[x][t] = f[x][t - j] + f[y][j];
    

    代码

    //不小心把题目的k和s搞反了,但不影响结果,自己注意点看
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #define nn 310
    using namespace std;
    int son[nn] , nxt[nn] , head[nn] , id[nn];//链式前向星存子节点
    int fa[nn];
    inline void push(int s , int f){
    	static int top = 1;
    	son[top] = s;
    	nxt[top] = head[f];
    	head[f] = top;
    	top++;
    }
    
    int f[nn][nn];
    int n , m;
    int k[nn];
    void dp(int x){
    	f[x][0] = 0;
    	for(int i = head[x] ; i ; i = nxt[i]){
    		int y = son[i];
    		dp(y);
    		//倒序循环当前选课总门数(当前背包体积) 
    		for(int t = m ; t >= 0 ; t--)
    			//循环更深子树上的选课门数(组内物品)
    			//此处使用倒序是为了正确处理组内体积为0的物品,这里不太明白为什么会有体积为0的物品
    			for(int j = t ; j >= 0 ; j--)
    				if(t - j >= 0)
    					if(f[x][t] < f[x][t - j] + f[y][j])
    						f[x][t] = f[x][t - j] + f[y][j];
    	}
    	if(x != 0)//x不为0时,选修x本身只需要占用 一门课,获得相应学分 
    		for(int t = m ; t > 0 ; t--)
    			f[x][t] = f[x][t - 1] + k[x];
    }
    int main(){
    	cin >> n >> m;
    	for(int i = 1 , s ; i <= n ; i++){
    		cin >> s >> k[i];
    		push(i , s);
    	}
    	dp(0);
    	cout << f[0][m];
    	return 0;
    } 
    
  • 相关阅读:
    Vue的生命周期(钩子函数)
    Vue.set全局操作
    Vue.extend提供自定义组件的构造器
    Vue.directive自定义指令
    vuejs全局api概念
    v-pre原样输出&&v-once只加载一次
    v-model双向数据绑定
    OpenGL:基本算法
    OpenGL:基本图形绘画二
    OpenGL:基本图形绘画
  • 原文地址:https://www.cnblogs.com/dream1024/p/13957529.html
Copyright © 2011-2022 走看看