Vijos 1523 贪吃的九头龙 【树形DP】

贪吃的九头龙

背景

安徽省芜湖市第二十七中学测试题

NOI 2002 贪吃的九头龙(dragon)

Description:Official
Data:Official
Program:Converted by JackDavid127

描述

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

有一天,有M个脑袋的九头龙看到一棵长有N个果子的果树,喜出望外,恨不得一口把它全部吃掉。可是必须照顾到每个头,因此它需要把N个果子分成M组,每组至少有一个果子,让每个头吃一组。

这M个脑袋中有一个最大,称为“大头”,是众头之首,它要吃掉恰好K个果子,而且K个果子中理所当然地应该包括唯一的一个最大的果子。果子由N-1根树枝连接起来,由于果树是一个整体,因此可以从任意一个果子出发沿着树枝“走到”任何一个其他的果子。

对于每段树枝,如果它所连接的两个果子需要由不同的头来吃掉,那么两个头会共同把树枝弄断而把果子分开;如果这两个果子是由同一个头来吃掉,那么这个头会懒得把它弄断而直接把果子连同树枝一起吃掉。当然,吃树枝并不是很舒服的,因此每段树枝都有一个吃下去的“难受值”,而九头龙的难受值就是所有头吃掉的树枝的“难受值”之和。

九头龙希望它的“难受值”尽量小,你能帮它算算吗?

格式

输入格式

输入的第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。

输出格式

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

样例1

样例输入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

样例输出1

4

提示

树形动态规划

题目链接:

  https://www.vijos.org/p/1523

题目大意:

  N个果子的一颗树,树的边权都有一个值。九头龙有M个脑袋,1号脑袋(大头)必须吃1号果子,且1号脑袋必须吃恰好K个果子。

  其他的脑袋(小头)至少吃一个果子。如果一个树枝的两段都被同一个头吃掉,那么代价就加上这条边的值。问满足题意的最小代价。

题目思路:

  【树形DP】

  首先通过观察我们发现这题的M只存在两种情况,M=2和M>2

  如果M>2,那么通过交换必然有一种安排使得每个头都有至少一个果子吃且小头不会吃相邻的果子。

  所以只需要考虑一个果子是否被大头吃,共两种状态。如果M=2,则必须算上小头吃的相邻果子的代价。

  因为是一棵多叉树,转二叉树后为左儿子右兄弟,所以需要记录的是父亲的状态(二叉形态下的右兄弟需要知道原先多叉形态下父亲的状态)

  转移的时候f[i][j][k]表示节点i,以i为根的子树(含i)被大头吃掉j个果子,父亲(多叉下)状态为k的最小代价。

  k=0表示该节点的父亲(多叉下)被小头吃,k=1表示该节点的父亲(多叉下)被大头吃的代价。

  那么只需要枚举当前节点被大头还是小头吃即可。

  

 1 /****************************************************
 2
 3     Author : Coolxxx
 4     Copyright 2017 by Coolxxx. All rights reserved.
 5     BLOG : http://blog.csdn.net/u010568270
 6
 7 ****************************************************/
 8 #include<bits/stdc++.h>
 9 #pragma comment(linker,"/STACK:1024000000,1024000000")
10 #define abs(a) ((a)>0?(a):(-(a)))
11 #define lowbit(a) (a&(-a))
12 #define sqr(a) ((a)*(a))
13 #define mem(a,b) memset(a,b,sizeof(a))
14 #define eps (1e-8)
15 #define J 10000
16 #define mod 1000000007
17 #define MAX 0x7f7f7f7f
18 #define PI 3.14159265358979323
19 #define N 304
20 using namespace std;
21 typedef long long LL;
22 double anss;
23 LL aans;
24 int cas,cass;
25 int n,m,lll,ans;
26 int l[N],r[N],q[N],s[N],fa[N];
27 int ma[N][N];
28 int f[N][N][2];
29 void dfs(int now,int ff)
30 {
31     if(!now)return;
32     fa[now]=ff;
33     if(l[now])dfs(l[now],now);
34     if(r[now])dfs(r[now],now);
35     s[now]=s[l[now]]+s[r[now]]+1;
36     q[++lll]=now;
37 }
38 int main()
39 {
40     #ifndef ONLINE_JUDGE
41     freopen("1.txt","r",stdin);
42 //    freopen("2.txt","w",stdout);
43     #endif
44     int i,j,k;
45     int x,y,z;
46 //    for(scanf("%d",&cass);cass;cass--)
47 //    for(scanf("%d",&cas),cass=1;cass<=cas;cass++)
48 //    while(~scanf("%s",s))
49     while(~scanf("%d",&n))
50     {
51         mem(l,0);mem(r,0);mem(f,1);
52         scanf("%d%d",&m,&cas);
53         cass=(m==2);
54         for(i=1;i<n;i++)
55         {
56             scanf("%d%d%d",&x,&y,&z);
57             if(x>y)swap(x,y);
58             if(!l[x])
59             {
60                 l[x]=y;
61                 ma[x][y]=ma[y][x]=z;
62             }
63             else
64             {
65                 r[y]=l[x];
66                 l[x]=y;
67                 ma[x][y]=ma[y][x]=z;
68                 ma[y][r[y]]=ma[r[y]][y]=ma[x][r[y]];
69             }
70         }
71         if(m+cas>n){puts("-1");continue;}
72         lll=0;
73         dfs(1,0);
74         f[0][0][0]=f[0][0][1]=0;
75         for(x=1;x<=lll;x++)
76         {
77             i=q[x];
78             for(j=0;j<=min(cas,s[i]);j++)
79             {
80                 for(y=0;y<=j;y++)
81                 {
82                     for(k=0;k<=1;k++)
83                     {
84                         f[i][j][k]=min(f[i][j][k],f[l[i]][y][0]+f[r[i]][j-y][k]+ma[i][fa[i]]*(k==0)*cass);
85                         if(y>0)f[i][j][k]=min(f[i][j][k],f[l[i]][y-1][1]+f[r[i]][j-y][k]+ma[i][fa[i]]*(k==1));
86                     }
87                 }
88             }
89         }
90         printf("%d\n",f[l[1]][cas-1][1]);
91     }
92     return 0;
93 }
94 /*
95 //
96
97 //
98 */

时间: 2024-12-25 11:24:05

Vijos 1523 贪吃的九头龙 【树形DP】的相关文章

Vijos1523 NOI2002 贪吃的九头龙 树形dp

思路不算很难,但细节处理很麻烦 前面建图.多叉转二叉,以及确定dp处理序列的过程都是套路,dp的状态转移过程以注释的形式阐述 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <queue> 5 6 int N,M,K; 7 8 struct Edge 9 { 10 int to,next; 11 int weight; 12 void assign(int

vijos p1523 贪吃的九头龙(未完成)

1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 int point[303],next[603],v[603],c[603],cnt=0,N,M,K,f[303][303][2]; 6 bool p[303]; 7 void insect(int x,int y,int z){next[cnt]=point[x];point[x]=cnt;v[cn

多叉树转二叉树+树形dp(codevs 1746 贪吃的九头龙 2002noi)

题目传送门 看到这个题目我们要先把问题简化了,条件中是多叉树,我们可以把它转换成二叉树,左边是儿子右边是兄弟的储存方式. 首先先判断否的部分,当总的果子小于需求,也就是N-k<M-1时输出-1. 我们再判断是的部分 如果没有大头,一定存在难受值为0的方案但是现在题目中有大头,我们就可以按按照小头的个数进行分类 1.有一个小头,我们要考虑小头和大头的难受值之和. 2.有多个小头,因为小头可以在奇偶的进行变换,所以我们只需要考虑大头的难受值. 分析到这里,我们就可以发现是树形dp我们设f[i][j]

NOI2002 贪吃的九头龙

[问题描述] 传说中的九头龙是一种特别贪吃的动物.虽然名字叫"九头龙",但这只是说它出生的时候有九个头,而在成长的过程中,它有时会长出很多的新头,头的总数会远大于九,当然也会有旧头因衰老而自己脱落. 有一天,有M个脑袋的九头龙看到一棵长有N个果子的果树,喜出望外,恨不得一口把它全部吃掉.可是必须照顾到每个头,因此它需要把N个果子分成M组,每组至少有一个果子,让每个头吃一组. 这M个脑袋中有一个最大,称为"大头",是众头之首,它要吃掉恰好K个果子,而且K个果子中理所当

codevs贪吃的九头龙

传说中的九头龙是一种特别贪吃的动物.虽然名字叫“九头龙”,但这只是说它出生的时候有九个头,而在成长的过程中,它有时会长出很多的新头,头的总数会远大于九,当然也会有旧头因衰老而自己脱落.有一天,有M 个脑袋的九头龙看到一棵长有N 个果子的果树,喜出望外,恨不得一口把它全部吃掉.可是必须照顾到每个头,因此它需要把N 个果子分成M组,每组至少有一个果子,让每个头吃一组.这M个脑袋中有一个最大,称为“大头”,是众头之首,它要吃掉恰好K个果子,而且K个果子中理所当然地应该包括唯一的一个最大的果子.果子由N

贪吃的九头龙

树形dp #include<bits/stdc++.h> #define N 305 using namespace std; struct LEB{ int to,nxt,w; }e[N<<1]; int f[N][N][2]; int tmp[N][2]; int head[N]; int n,m,k,x,z,y,cnt; void Build(int x,int y,int z){ e[++cnt]=(LEB){y,head[x],z}; head[x]=cnt; } voi

codevs 1746 贪吃的九头龙

/* 状态定义的没错 就是考试的时候傻啦吧唧的转移左右孩子 其实之转移父亲就简单多了 不用考虑那么多 还有就是偷懒没有把谁有没有找过这个信息转过去 而是搞了个全局变量…wa到挺 再就是特盘的时候还有终止条件写的不好 写的时间也很长 ….. */ #include<iostream> #include<cstdio> #include<cstring> #define maxn 510 #define inf 0x3f3f3f3f using namespace std;

vijos 1313 金明的预算方案 树形DP

描述 金明今天很开心,家里购置的新房就要领钥匙了,新房里有一间金明自己专用的很宽敞的房间.更让他高兴的是,妈妈昨天对他说:“你的房间需要购买哪些物品,怎么布置,你说了算,只要不超过N元钱就行”.今天一早,金明就开始做预算了,他把想买的物品分为两类:主件与附件,附件是从属于某个主件的,下表就是一些主件与附件的例子:主件 附件电脑 打印机,扫描仪书柜 图书书桌 台灯,文具工作椅 无如果要买归类为附件的物品,必须先买该附件所属的主件.每个主件可以有0个.1个或2个附件.附件不再有从属于自己的附件.金明

【vijos】1892 树上的最大匹配(树形dp+计数)

https://vijos.org/p/1892 这个必须得卡评测机+手动开栈才能卡过QAQ 手动开栈我百度的... int size=256<<20; //256MB char *p=(char*)malloc(size)+size; __asm__("movl %0, %%esp\n" :: "r"(p)); 然后我交了无数发,然后才卡过.... 我们设状态 f[i][0]表示i节点与儿子的边一个也不选 f[i][1]表示i节点只选一条与儿子的边 g