TYVJ P1051 选课

目录:


题目:

传送门


分析:

经典的树形dp
f[k][y] f [ k ] [ y ] 为在以 k k 为根的子树中,选择y个课程的最大学分
根据题意,当我们选择了一门先修课程,我们的子节点就可以进行选择,所有得出转移方程:

f[k][y]=max{f[k][y],f[k][yj]+f[s][j]} f [ k ] [ y ] = m a x { f [ k ] [ y ] , f [ k ] [ y − j ] + f [ s ] [ j ] }

s s 表示k的一个子节点, j j 表示以s为根,可以达到最大学分的课程选择数


代码:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>  
#include<cstdlib>
#include<algorithm>
#include<set>
#include<vector>
#include<map>
#include<list>
#include<ctime>
#include<iomanip>
#include<string>
#include<bitset>
#define LL long long
#define h happy
using namespace std;
inline LL read() {
    LL d=0,f=1;char s=getchar();
    while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
    while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}
    return d*f;
}
int n=read(),m=read();
vector<int> son[301];
int min(int x,int y)
{
    return x<y? x:y;
}
int max(int x,int y)
{
    return x>y? x:y;
}
int p[301],f[301][301];
void dp(int k)
{
    f[k][0]=0;
    for(int i=0;i<son[k].size();i++)
    {
        int s=son[k][i];
        dp(s);
        for(int y=m;y>=0;y--)
          for(int j=y;j>=0;j--)
            if(y-j>=0)
              f[k][y]=max(f[k][y],f[k][y-j]+f[s][j]);
    }
    if(k)
      for(int y=m;y>0;y--)
        f[k][y]=f[k][y-1]+p[k];
    return;
}
int main()
{
    for(int i=1;i<=n;i++)
    {
        int f=read();
        p[i]=read();
        son[f].push_back(i);
    }
    dp(0);
    printf("%d",f[0][m]);
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值