zoukankan      html  css  js  c++  java
  • 【LOJ#10154】选课

    题目中所说的每门课都可能有先修课,也可能没有先修课,因此课与课之间的关系构成了一颗森林。
    这种树上选择若干物品的最优解问题对应着树形背包问题。

    阶段:子树的大小
    状态:在当前子树中,选取 i 门课能够获得的最多学分
    状态转移方程:(dp[u][t]=max{Sigma_{i=1}^pdp[v_i][c_i] }+mark[u],Sigma_{i=1}^pc_i=t-1)

    这种从每棵子树中选取若干物品的最优解问题可以转化成一个分组背包问题,其中子树的数量对应着物品组数,子树中选择的课程数量构成组内物品,符合每次只能在子树中选择一个固定的课程数量。

    代码如下:

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn=310;
    
    int n,m,dp[maxn][maxn],mark[maxn];
    vector<int> G[maxn];
    
    inline void add_edge(int from,int to){G[from].push_back(to);}
    
    void read_and_parse(){
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;i++){
    		int pre;scanf("%d%d",&pre,&mark[i]);
    		add_edge(pre,i);
    	}
    }
    
    void dfs(int u){
    	for(int i=0;i<G[u].size();i++){
    		int v=G[u][i];
    		dfs(v);
    		for(int j=m;j>=0;j--)//倒序循环
    			for(int k=0;k<=j;k++)
    				dp[u][j]=max(dp[u][j],dp[u][j-k]+dp[v][k]);
    	}
    	if(u!=0)
    		for(int j=m;j>=1;j--)
    			dp[u][j]=dp[u][j-1]+mark[u];
    }
    
    void solve(){
    	dfs(0);
    	printf("%d
    ",dp[0][m]);
    }
    
    int main(){
    	read_and_parse();
    	solve();
    	return 0;
    }
    
  • 相关阅读:
    Cesium加载倾斜摄影数据
    CentOS7安装Docker
    Docker镜像下载
    c#验证密码强度
    配置阿里yum源
    ftpbat脚本
    powershell-ftpmove文件到本地
    Session Setup Request,NTLMSSP_AUTH, User:Dmainhostname$
    smblog
    树莓派显示器屏幕休眠
  • 原文地址:https://www.cnblogs.com/wzj-xhjbk/p/9870588.html
Copyright © 2011-2022 走看看