zoukankan      html  css  js  c++  java
  • 选课

    https://loj.ac/problem/10154

    题目描述

      给出(n)门课及其先修课,每门课有一定学分,求选(m)门课能获得的最大学分。

    思路

      由于原图可能是森林,可以先建一个虚根(0)号节点。我们考虑用(f[i][j])表示以(i)为根的子树的选(j)门课能获得的最大学分,并且(i)这门课必选,那么对于(f[i][j]),其答案就是在每个子树中分别选(k)门课和其他子树中选(j-k)门课的答案。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    
    vector<int>son[110];
    int n,m,f[110][110],a[110];
    void dfs(int u)
    {
    	f[u][0]=0;
    	for(int i=0;i<son[u].size();i++)
    	{
    		int v=son[u][i];
    		dfs(v);
    		for(int j=n;j>=0;j--)
    			for(int k=j;k>=0;k--)
    				f[u][j]=max(f[u][j],f[u][j-k]+f[v][k]);
    	}
    	if(u)
    		for(int i=n;i>=1;i--)
    			f[u][i]=f[u][i-1]+a[u];
    }
    
    int read()
    {
    	int res=0,w=1;
    	char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){res=(res<<3)+(res<<1)+(ch^48);ch=getchar();}
    	return res*w;
    }
    void write(int x)
    {
    	if(x<0){putchar('-');x=-x;}
    	if(x>9)write(x/10);
    	putchar(x%10+'0');
    }
    void writeln(int x)
    {
    	write(x);
    	putchar('
    ');
    }
    
    int main() 
    {
    	m=read(),n=read();
    	for(int i=1;i<=m;i++)
    	{
    		int x=read();a[i]=read();
    		son[x].push_back(i);
    	}
    	dfs(0);
    	writeln(f[0][n]);
    }
    
  • 相关阅读:
    四则运算 2
    《你的灯亮着吗》读后感 (前两篇)
    四则运算设计思路
    读书目标
    课堂总结
    人月神话感想
    软件工程概论11
    软件工程概论10
    bnu——GCD SUM (莫比乌斯反演)
    POJ1108_Split Windows 解题报告
  • 原文地址:https://www.cnblogs.com/fangbozhen/p/11838011.html
Copyright © 2011-2022 走看看