zoukankan      html  css  js  c++  java
  • CTSC1998 选课(背包类树形Dp)

    题意:

    给出 n 节课的先修课号以及学分(先修课号指的是在学习某节课时先需要学习的课程),求学 m 节课的最大学分。

    细节:

    1、对于课程 a 其先修课号为 b ,对于课程 b 其先修课号为 c ,则需要学 a 的方式必须为先学 c 在学 b
    2、可能存在多门课程没有先修课号。

    分析:

    题目给出的先修课号是唯一的,所以我们可以将这种依赖关系构建成一棵树,所以对于每个节点的学分之和就是为从根节点到其的简单路径,所以对于每个节点相当于一个背包。

    所以状态就是:dp[u][j] 表示以 u 为根的子树选了 j 门课所获得最大学分

    转移就是:dp[u][j] = max( dp[u][j] , dp[u][j-k] + dp[v][k] )
    其中 dp[u][1] = dist[u] , 1 ≤ j ≤ size[u] , 0≤k≤min( size[v] , j-1)

    代码:

    #include <bits/stdc++.h>
    #define MAXN 305
    using namespace std;
    
    int f[MAXN][MAXN], dist[MAXN], size[MAXN], n, m;
    vector <int> G[MAXN];
    
    void build(int u){
    	size[u]=1;
    	for (int i=0; i<G[u].size(); i++){
    		int v=G[u][i];
    		build(v);
    		size[u]+=size[v];
    	}
    
    }
    
    void solve(int u){
    	f[u][1]=dist[u];
    	for (int i=0; i<G[u].size(); i++){
    		int v=G[u][i];
    		solve(v);
    		for (int j=min(size[u], m+1); j>=2; j--)
    			for (int k=0; k<=min(size[v], j-1); k++)
    				f[u][j]=max(f[u][j], f[u][j-k]+f[v][k]); 
    	}
    }
    
    int main(){
    	scanf("%d%d", &n, &m);
    	for (int i=1, x; i<=n; i++){
    		scanf("%d%d", &x, &dist[i]);
    		G[x].push_back(i);
    	}
    	memset(f, 0, sizeof f);
    	build(0);
    	solve(0);
    	printf("%d\n", f[0][m+1]);
    	return 0;
    }
    
  • 相关阅读:
    6. Flask请求和响应
    5. Flask模板
    FW:Software Testing
    What is the difference between modified duration, effective duration and duration?
    How to push master to QA branch in GIT
    FTPS Firewall
    Query performance optimization of Vertica
    (Forward)5 Public Speaking Tips That'll Prepare You for Any Interview
    (转)The remote certificate is invalid according to the validation procedure
    Change
  • 原文地址:https://www.cnblogs.com/xiannvzuimei/p/9961214.html
Copyright © 2011-2022 走看看