博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
HDU 1561 (树形DP+背包)
阅读量:5834 次
发布时间:2019-06-18

本文共 1308 字,大约阅读时间需要 4 分钟。

题目链接

题目大意:从树根开始取点。最多取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, 不过要多好多次没必要的循环。

#include "cstdio"#include "vector"#include "cstring"using namespace std;#define maxn 205int n,m,u,dp[maxn][maxn],w[maxn],head[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,cost=1,f=0;    for(int i=cost;i<=m;i++) dp[root][i]=w[root];    if(head[root]==-1) return 1;    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>=1;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+1;}int main(){    //freopen("in.txt","r",stdin);    while(scanf("%d%d",&n,&m)&&n&&m)    {        memset(head,-1,sizeof(head));        tol=0;        for(int i=1;i<=n;i++)        {            scanf("%d%d",&u,&w[i]);            addedge(u,i);        }        dfs(0);        printf("%d\n",dp[0][m+1]);        memset(dp,0,sizeof(dp));    }}

 

11910646 2014-10-19 14:01:53 Accepted 0MS 400K C++

转载地址:http://joucx.baihongyu.com/

你可能感兴趣的文章
C++_了解虚函数的概念
查看>>
全新jmeter视频已经上架
查看>>
Windows 8下如何删除无线配置文件
查看>>
oracle系列(五)高级DBA必知的Oracle的备份与恢复(全录收集)
查看>>
hp 服务器通过串口重定向功能的使用
查看>>
国外10大IT网站和博客网站
查看>>
android第十一期 - SmoothSwitchLibrary仿IOS切换Activity动画效果
查看>>
zabbix 批量web url监控
查看>>
MongoDB CookBook读书笔记之导入导出
查看>>
shell如何快速锁定所有账号
查看>>
HTML 5实现的手机摇一摇
查看>>
此博客不再发表对自己私事的看法
查看>>
导致Asp.Net站点重启的10个原因
查看>>
【PMP】Head First PMP 学习笔记 第一章 引言
查看>>
抓住云机遇编排工作 搞定复杂IT工作流
查看>>
MYSQL的longtext字段能放多少数据?
查看>>
MTK 平台上如何给 camera 添加一种 preview size
查看>>
云计算最大难处
查看>>
关于数据分析思路的4点心得
查看>>
Memcached安装与配置
查看>>