传说中的九头龙是一种特别贪吃的动物。虽然名字叫“九头龙”,但这只是说它出生的时候有九个头,而在成长的过程中,它有时会长出很多的新头,头的总数会远大于九,当然也会有旧头因衰老而自己脱落。
有一天,有M个脑袋的九头龙看到一棵长有N个果子的果树,喜出望外,恨不得一口把它全部吃掉。可是必须照顾到每个头,因此它需要把N个果子分成M组,每组至少有一个果子,让每个头吃一组。
这M个脑袋中有一个最大,称为“大头”,是众头之首,它要吃掉恰好K个果子,而且K个果子中理所当然地应该包括唯一的一个最大的果子。果子由N-1根树枝连接起来,由于果树是一个整体,因此可以从任意一个果子出发沿着树枝“走到”任何一个其他的果子。
对于每段树枝,如果它所连接的两个果子需要由不同的头来吃掉,那么两个头会共同把树枝弄断而把果子分开;如果这两个果子是由同一个头来吃掉,那么这个头会懒得把它弄断而直接把果子连同树枝一起吃掉。当然,吃树枝并不是很舒服的,因此每段树枝都有一个吃下去的“难受值”,而九头龙的难受值就是所有头吃掉的树枝的“难受值”之和。
九头龙希望它的“难受值”尽量小,你能帮它算算吗?
例如图1所示的例子中,果树包含8个果子,7段树枝,各段树枝的“难受值”标记在了树枝的旁边。九头龙有两个脑袋,大头需要吃掉4个果子,其中必须包含最大的果子。即N=8,M=2,K=4:

图一描述了果树的形态,图二描述了最优策略。

输入格式:

输入文件dragon.in的第1行包含三个整数N (1<=N<=300),M (2<=M<=N),K (1<=K<=N)。 N个果子依次编号1,2,...,N,且最大的果子的编号总是1。第2行到第N行描述了果树的形态,每行包含三个整数a (1<=a<=N),b (1<=b<=N),c (0<=c<=105),表示存在一段难受值为c的树枝连接果子a和果子b。

输出格式:

输出文件dragon.out仅有一行,包含一个整数,表示在满足“大头”的要求的前提下,九头龙的难受值的最小值。如果无法满足要求,输出-1。

样例输入:

8 2 4
1 2 20
1 3 4
1 4 13
2 5 10
2 6 12
3 7 15
3 8 5

样例输出:

4

数据范围:

(1<=N<=300),M (2<=M<=N),K (1<=K<=N)
(1<=a<=N),b (1<=b<=N),c (0<=c<=105),

时间限制:

1S

空间限制:

256M

提示:

【样例说明】

该样例对应于题目描述中的例子。

QAQ终于孙过了这道题,好累啊!!!OwO

本题是细节难题。

树转二叉树的具体方法是

将该点的第一个儿子作为左儿子,该点的右儿子为他的兄弟。

-1的情况好判只需要n-kk<m-1时,即不是所有头都吃得到果子时无解。

当有解时,

可以证明当吃法无大头限制时,你可以不费难受值吃完(只需按层奇偶用两个交替排放,再那剩下的一个换一个即可)。

又因为该图满足n-1条边,n个点,所以是棵树。

我们可以先将树转二叉树,方便操作。

我们令f[i][j][k]为该节点为i,该子树中有j个大头吃的点,k=0表示该点的父亲不为大头(attention!!),k=1表示为大头。

f[i][j][k]为i点的儿子和i点以后的兄弟和i点大头吃j个,k状态的最小难受值。

枚举j1即其儿子的状态分担的大头个数,为方便枚举,f1分担个数为j1-1;

j1的边界从0到该点子树元素个数和j的较小值

f1[i][j][k]=f(l[i],j1-1,1)+ohno(k,1)*dis[i];
f2[i][j][k]=f(l[i],j1,0)+ohno(k,0)*dis[i];
int t=min(f1[i][j][k],f2[i][j][k])+f(r[i],j-j1,k);
f[i][j][k]=min(f[i][j][k],t);

ohno的定义

1)若i=1且j=1,则大头吃下了相连的果子,需要付出难受值,返回1;

2)若i=0且j=0,但M=2,只有一个小头,小头吃下了相连的果子,需要付出难受值,返回1;

3)其它情况,总有办法分配果子使得九头龙不付出难受值,返回0。

解释2):当m>2时除大头外的头一定能够使剩下的枝不被吃,证明见上。而m=2时则剩下的枝会被同一枝吃,所以这么做。

注意:输出的是递归1的儿子。要记忆化。边界见程序,dp是记忆化过程。
上代码兄弟们:
#include<bits/stdc++.h>
using namespace std;
int r[301],l[301],dis[301],sonnum[301];
int f1[301][301][2],f2[301][301][2],f[301][301][2];
int n,m,kk;
//World start now WITH ME!
//每次扫到没有兄弟或儿子时,又不需要有大头吃时just return 0;
//要大头吃这是不可能的just return an BIGNUM; 
//k为i的父亲是否被大头吃。。 
//重点!!!以后与这种题子树节点数考虑!!! 
//最大值设大!!!答案大于300001!!!否则9错 
int ohno(int xx,int yy) //判有没有吃树枝
{
if (xx==1&&yy==1) return 1;
if(xx==0&&yy==0&&m==2) return 1;
return 0;

int num_of_son_trees(int x)
{
if(x==0) return 0;
sonnum[x]=num_of_son_trees(l[x])+num_of_son_trees(r[x])+1;
return sonnum[x];
}
inline int dp(int i,int j,int k)
{
if (j<0) return 30000001;
if (f[i][j][k]>=0) return f[i][j][k];
if(i==0&&j==0) return 0;
if(i==0&&j) return 30000001;
f1[i][j][k]=30000001;
f2[i][j][k]=30000001;
f[i][j][k]=30000001;
for(int j1=0;j1<=min(j,sonnum[i]);j1++)
{
f1[i][j][k]=dp(l[i],j1-1,1)+ohno(k,1)*dis[i];
f2[i][j][k]=dp(l[i],j1,0)+ohno(k,0)*dis[i];
int t=min(f1[i][j][k],f2[i][j][k])+dp(r[i],j-j1,k);
f[i][j][k]=min(f[i][j][k],t);
}
//        q[x][y][z]=min(q[x][y][z],min( dp(p[x].l,i,0)+(m==2)*(z==0)*p[x].d , dp(p[x].l,i-1,1)+(z==1)*p[x].d )+dp(p[x].r,y-i,z) );
return f[i][j][k];
}
int main()
{
cin>>n>>m>>kk;
if(n-kk<m-1) 
{
cout<<"-1";
return 0;
}
for(int i=1;i<=n-1;i++)
{
int x,y,d;
cin>>x>>y>>d;
r[y]=l[x];
l[x]=y;
dis[y]=d;
}
l[0]=1;
num_of_son_trees(1);
int tot=30000001;
for(int i=0;i<=300;i++)
for(int j=0;j<=300;j++)
for(int k=0;k<=1;k++)
f[i][j][k]=-1;
// for(int i=kk;i<=n-m+1;i++)
//只能吃kk个不能多吃 
{
tot=min(tot,dp(l[1],kk-1,1));
}
cout<<tot<<"\n";
}

Treedp贪吃的九头龙详解相关推荐

  1. NOI2002 贪吃的九头龙

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

  2. vijos 1523 贪吃的九头龙

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

  3. BSOJ 1480 贪吃的九头龙

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

  4. codevs贪吃的九头龙

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

  5. codevs1746 贪吃的九头龙

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

  6. 【NOI2002】贪吃的九头龙

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

  7. HTTP协议的头信息详解

    HTTP协议的头信息详解 http://blog.csdn.net/guoguo1980/archive/2008/07/14/2649658.aspx HTTP协议的头信息详解 HTTP(Hyper ...

  8. linux语言的说明顺序有哪些,(linux常用头文件详解.doc

    (linux常用头文件详解 linux常用头文件详解 POSIX标准定义的头文件??????? 目录项 ???????? 文件控制 ??? 文件名匹配类型 ??? 路径名模式匹配类型 ??????? ...

  9. linux 常用头文件,(常用头文件详解.doc

    (常用头文件详解 linux常用头文件详解 POSIX标准定义的头文件??????? 目录项 ???????? 文件控制 ??? 文件名匹配类型 ??? 路径名模式匹配类型 ??????? 组文件 ? ...

  10. from mysql partition select_爬虫(九十九)mysql详解二

    **mysql中字段的常见类型: ** 二进制位 bit(长度) tinyint[(长度)] [有无符号unsigned] [位数低于长度时候是否填充零zerofill] 有符号表示范围-128 ~ ...

最新文章

  1. java unit包_Java接入UNIT文本对话处理源码详解
  2. jquery 插件
  3. win10系统如何安装iis信息服务器,win10系统安装iis服务功能的具体方法【图文教程】...
  4. Python 使用sys.exc_info自己捕获异常详细信息
  5. OSGi-入门篇之服务层(03)
  6. 如何通过c语言获取ipv6邻居表,急求在vc++6.0中获取IPV6地址的方法,高手请进,谢谢!!...
  7. java整数的反转_反转Java中的整数
  8. 如果使用StateServer或SQLServer,会遇到的问题。。。。
  9. 设计模式 原型模式_设计模式:原型
  10. python ftp下载文件_文件上传下载Python
  11. Java IO类库之CharArrayWriter
  12. Ubuntu18.04安装OpenPCDet及配置spconv
  13. java 实现根据ip重定向_从0到1用java再造tcpip协议栈:代码实现ping应用功能1
  14. 关于应用的外部接口设计心得
  15. Opencv速成笔记--图像处理1
  16. eclipse 编译器 unhandled event loop exception 异常解决办法
  17. matlab 离散求偏导,matlab怎么求离散曲面的偏导数
  18. android LBS模式,android: 如何开启webview的LBS功能
  19. Python进行各项统计检验
  20. 网页模板UI素材推荐 精品 小众

热门文章

  1. DAOS 系统内部介绍(一)—— 概述
  2. 罗格斯大学电子与计算机系排名,罗格斯大学EE排名2020年,网上最详细技巧汇总篇...
  3. HTML5CSS3:Day03 2D动画 3D动画 CSS3过渡
  4. 高德地图大头针功能_有关于高德地图的大头针下落动画。还有就是高德地图的设置...
  5. Default interface methods are only supported starting with Android N (--min-api 24):
  6. xy苹果助手未受信任_苹果ios企业签名后App无法安装?如何解决?
  7. 华为这个广告,我愿一辈子不买苹果!
  8. i春秋——“百度杯”CTF比赛 十月场——Vld(Vulcan Logic Dumper 、php opcode、sql 报错注入)...
  9. Vulcan 基于Meteor的APollO框架 , grapesjs 用于可视化生成Html 页面
  10. 一:log4j2配置文档