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

我们用dp(i,j,k)来表示此状态下最小难受值,i为当前访问到的节点,j为大头还要吃几个,k为当前节点的父节点的颜色。

我们会发现只要小头的数目大于1,我们一定保证当树枝的两端被小头吃时,不会增加难受值,那么难受值就由大头增加。

用1表示大头吃,0表示小头吃。d[i][j]表示当树枝的两端分别被i吃和被j吃时,是否会产生难受值。

d[1][1]=1; d[0][0]=m>2?0:1; d[1][0]=d[0][1]=0;

f[i][j][k]=min(f[son[i]][p][1]+f[brother[i]][j-p-1][k]+cost[i]*d[k][1],f[son[i]][p][0]+f[brother[i]][j-p][k]+cost[i]*d[k][0]);

//分别代表当前节点被大头吃还是被小头吃的情况。

具体的一些剪枝和细节写程序注释里

程序:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
struct ding{int to,next,c;
}edge[1000],e[1000];
int f[1000][1000][2],d[2][2];
int num[1000],cost[1000],head[1000],h[1000],n,cnt,son[1000],lef[1000],righ[1000];
bool vis[1000];
void add1(int u,int v,int w){e[++cnt].to=v;e[cnt].next=h[u];e[cnt].c=w;h[u]=cnt;}
void add2(int u,int v){edge[++cnt].to=v; edge[cnt].next=head[u]; head[u]=cnt;}
void dfs(int x)
{vis[x]=true;for (int i=h[x];i;i=e[i].next)if (!vis[e[i].to]) {add2(x,e[i].to);cost[e[i].to]=e[i].c;dfs(e[i].to);}
}
int dfs2(int x)
{if (x==0) return 0;num[x]=dfs2(lef[x])+dfs2(righ[x])+1;return num[x];
}
int dp(int root,int tot,int now)
{ if (tot<0) return 210000000;
//如果已经不需要再取if (f[root][tot][now]!=-1) return f[root][tot][now];//记忆化搜索if (tot>num[root]) return f[root][tot][now]=210000000;//如果说当前节点的子节点加上兄弟节点的数目还是小于大头要吃的数目,那么永远也取不到,是不合法的。if ((root==0)&&(tot==0)) return f[root][tot][now]=0;
//初始节点if (root==0) return  f[root][tot][now]=210000000;
//情况不合法int ans;  ans=210000000;for (int i=0;i<=tot;i++){ans=min(ans,dp(lef[root],i,1)+dp(righ[root],tot-i-1,now)+cost[root]*d[now][1]);ans=min(ans,dp(lef[root],i,0)+dp(righ[root],tot-i,now)+cost[root]*d[now][0]);}return f[root][tot][now]=ans;
}
int main()
{int k,m;scanf("%d%d%d",&n,&m,&k);    if (m+k-1>n){cout<<"-1"<<endl;return 0;}//如果果子不够吃,就属特殊情况int u,v,c1;for (int i=1;i<=n-1;i++){scanf("%d%d%d",&u,&v,&c1);add1(u,v,c1); add1(v,u,c1);}cnt=0;dfs(1);
//先深搜出这棵树的状态for (int j=1;j<=n;j++)for (int i=head[j];i;i=edge[i].next){int y=edge[i].to;if (son[j]) righ[son[j]]=y;else lef[j]=y;son[j]=y;
//转为二叉树
  }d[1][1]=1; if (m==2) d[0][0]=1;
//num[[i]代表i的子树节点加上它的兄弟节点的数量。 num[1]=dfs2(lef[1])+dfs2(righ[1])+1;for (int i=0;i<=n;i++)for (int j=0;j<=k+1;j++)for (int z=0;z<=1;z++)f[i][j][z]=-1;cout<<dp(lef[1],k-1,1)<<endl; return 0;
} 

转载于:https://www.cnblogs.com/2014nhc/p/6625232.html

树形dp贪吃的九头龙(vijos1523)相关推荐

  1. vijos 1523 贪吃的九头龙

    http://www.elijahqi.win/archives/1191 背景 安徽省芜湖市第二十七中学测试题 NOI 2002 贪吃的九头龙(dragon) Description:Officia ...

  2. BSOJ 1480 贪吃的九头龙

    BSOJ 1480 贪吃的九头龙 NOI原题,下了数据,都过了.但是OJ现在挂了... 首先,脑袋的数量都是唬人的.如果至少3个脑袋的话,完全可以做到不让两个小头在一起(不过当只有2个头的时候得特别考 ...

  3. NOI2002 贪吃的九头龙

    P2940 贪吃的九头龙 时间: 1000ms / 空间: 65536KiB / Java类名: Main 描述 贪吃的九头龙(dragon.pas/c/cpp) [问题描述] 传说中的九头龙是一种特 ...

  4. codevs贪吃的九头龙

    传说中的九头龙是一种特别贪吃的动物.虽然名字叫"九头龙",但这只是说它出生的时候有九个头,而在成长的过程中,它有时会长出很多的新头,头的总数会远大于九,当然也会有旧头因衰老而自己脱 ...

  5. codevs1746 贪吃的九头龙

    [问题描述] 传说中的九头龙是一种特别贪吃的动物.虽然名字叫"九头龙",但这只是说它出生的时候有九个头,而在成长的过程中,它有时会长出很多的新头,头的总数会远大于九,当然也会有旧头 ...

  6. 【NOI2002】贪吃的九头龙

    Description 传说中的九头龙是一种特别贪吃的动物.虽然名字叫"九头龙",但这只是说它出生的时候有九个头,而在成长的过程中,它有时会长出很多的新头,头的总数会远大于九,当然 ...

  7. 九大背包问题专题--有依赖的背包问题(树形Dp结合)

    9.有依赖的背包问题 问题: 有N件物品和一个容量是V的背包. 物品之间具有依赖关系,且依赖关系组成一棵树的形状.如果选择一个物品,则必须选择它的父节点. 如图所示 如果选择物品5,则必须选择物品1和 ...

  8. LibreOJ #2478.「九省联考 2018」林克卡特树 树形dp+带权二分

    题意 给出一棵n个节点的树和k,边有边权,要求先从树中选k条边,然后把这k条边删掉,再加入k条边权为0的边,满足操作完后的图仍然是一棵树.问新树的带权直径最大是多少. n,k≤3∗105n,k≤3∗1 ...

  9. 最大搜索二叉子树大小(树形dp)

    给定一颗二叉树的头节点head,返回这棵二叉树中最大的二叉搜索子树 (二叉搜索树:该二叉树中左子树所有节点比它小,右子树所有节点比它大 ): 思路: 这是一道分析可能性求解在二叉树上做类似动态规划的问 ...

  10. 蓝桥杯节点选择(java)第一道树形dp分析

    蓝桥杯 节点选择 问题描述 有一棵 n 个节点的树,树上每个节点都有一个正整数权值.如果一个点被选择了,那么在树上和它相邻的点都不能被选择.求选出的点的权值和最大是多少? 输入格式 第一行包含一个整数 ...

最新文章

  1. 在 Linux 中如何禁止用户登录
  2. PowerBI随笔(3)-增加自定义列
  3. 算法优化:最大字段和,双指针遍历(n^2),分治法(nlogn),动态规划(n)
  4. React Native移动开发实战-4-Android平台的适配
  5. JAVA编程心得-JAVA实现CRC-CCITT(XMODEM)算法
  6. 什么样的程序算作漂亮的?
  7. NOI入门级数学: 数及其运算 数的进制之二进制
  8. 【2】SCN-Ribbon负载均衡
  9. 计算机应用技术爱岗敬业,高职专业人才培养方案(计算机应用技术).doc
  10. 【数据结构笔记31】Dijkstra算法例题:旅游规划(双权重),以及其他推广
  11. Linux后台运行python程序并输出到日志文件
  12. 番茄是水果还是蔬菜这事儿,居然闹到了最高法院?!
  13. DevOps使用教程 华为云(13)接口测试 怎么编辑设置 批量测试 测试套件
  14. MT4 CRM 源码
  15. [网络安全自学篇] 六十.Cracer第八期——(2)五万字总结Linux基础知识和常用渗透命令
  16. web第三课html课堂笔记
  17. Bytom BIP-32协议和BIP-44协议
  18. Python实现二维码生成器
  19. 树的中序遍历(递归,迭代,莫里斯)
  20. linux下安装录制视频软件Simple Screen Recorder

热门文章

  1. python中unique()与nuniqe()用法
  2. JAVA程序提取PDF中间页
  3. Android入门笔记11
  4. pycharm Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon run
  5. 在jupyter上绘制caffe网络迭代时的损失和精度曲线
  6. 如何开发神经网络来预测电离层中的干扰
  7. Ubuntu16.04 设置自启动脚本,系统重启自动执行自定义脚本任务
  8. 南昌大学计算机网络通信用什么书,南昌大学_计算机网络教材.doc
  9. 【Django 2021年最新版教程35】python+request+unittest 对Django接口进行测试
  10. linux shell grep 多个文件