码迷,mamicode.com
首页 > 其他好文 > 详细

Vijos 1180 (树形DP+背包)

时间:2014-10-17 21:43:54      阅读:181      评论:0      收藏:0      [点我收藏+]

标签:style   http   color   io   os   ar   for   strong   sp   

题目链接https://vijos.org/p/1180

题目大意:选课。只有根课选了才能选子课,给定选课数m, 问最大学分多少。

解题思路

树形背包。cost=1。

且有个虚根0,取这个虚根也要cost,所以最后的结果是dp[0][m+1]。

本题是cost=1的特殊背包问题,在两个for循环上有一个优化。

for(f+1...j....cost)

  for(1....k...j-cost)

其中f为当前已经dfs子结点个数。之所以+1,是因为根要预留一个空间。

f+=dfs(t),dfs(t)返回的是子点t的f+1。

其实可以直接把f+1写成m+1, 不过要多跑几次循环。

这种写法在POJ 1155中对于子结点不完全取将会起到很大作用。

 

#include "iostream"
#include "cstdio"
#include "cstring"
using namespace std;
#define maxn 305
int n,m,root,x;
int dp[maxn][maxn],head[maxn],w[maxn],tol;
struct Edge
{
    int to,next;
}e[maxn];
void addedge(int u,int v)
{
    e[tol].to=v;
    e[tol].next=head[u];
    head[u]=tol++;
}
int dfs(int root)
{
    int i=root,f=0,cost=1;
    for(int i=cost;i<=m;i++) dp[root][i]=w[root];
    for(int a=head[root];a!=-1;a=e[a].next)
    {
        int t=e[a].to;
        f+=dfs(t);
        for(int j=f+1; j>=cost; j--)
            for(int k=1; k<=j-cost; k++)
                dp[i][j]=max(dp[i][j],dp[i][j-k]+dp[t][k]);
    }
    return f+cost; //¸ùÒ²ÏûºÄ1
}
int main()
{
    //freopen("in.txt","r",stdin);
    scanf("%d%d",&n,&m);
    memset(head,-1,sizeof(head));
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d",&x,&w[i]);
        addedge(x,i);
    }
    dfs(0);
    printf("%d\n",dp[0][m+1]);
}

 

Accepted, time = 22 ms, mem = 924 KiB, score = 100

Vijos 1180 (树形DP+背包)

标签:style   http   color   io   os   ar   for   strong   sp   

原文地址:http://www.cnblogs.com/neopenx/p/4032015.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!