bzoj1812 [Ioi2005]riv
riv
几乎整个Byteland王国都被森林和河流所覆盖。小点的河汇聚到一起,形成了稍大点的河。就这样,所有的河水都汇聚并流进了一条大河,最后这条大河流进了大海。这条大河的入海口处有一个村庄——名叫Bytetown 在Byteland国,有n个伐木的村庄,这些村庄都座落在河边。目前在Bytetown,有一个巨大的伐木场,它处理着全国砍下的所有木料。木料被砍下后,顺着河流而被运到Bytetown的伐木场。Byteland的国王决定,为了减少运输木料的费用,再额外地建造k个伐木场。这k个伐木场将被建在其他村庄里。这些伐木场建造后,木料就不用都被送到Bytetown了,它们可以在 运输过程中第一个碰到的新伐木场被处理。显然,如果伐木场座落的那个村子就不用再付运送木料的费用了。它们可以直接被本村的伐木场处理。 注意:所有的河流都不会分叉,也就是说,每一个村子,顺流而下都只有一条路——到bytetown。 国王的大臣计算出了每个村子每年要产多少木料,你的任务是决定在哪些村子建设伐木场能获得最小的运费。其中运费的计算方法为:每一块木料每千米1分钱。 编一个程序: 1.从文件读入村子的个数,另外要建设的伐木场的数目,每年每个村子产的木料的块数以及河流的描述。 2.计算最小的运费并输出。Input第一行 包括两个数 n(2<=n<=100),k(1<=k<=50,且 k<=n)。n为村庄数,k为要建的伐木场的数目。除了bytetown外,每个村子依次被命名为1,2,3……n,bytetown被命名为0。 接下来n行,每行包涵3个整数 wi——每年i村子产的木料的块数 (0<=wi<=10000) vi——离i村子下游最近的村子(或bytetown)(0<=vi<=n) di——vi到i的距离(km)。(1<=di<=10000) 保证每年所有的木料流到bytetown的运费不超过2000,000,000分 50%的数据中n不超过20。Output输出最小花费,精确到分。Sample Input
4 2
1 0 1
1 1 10
10 2 5
1 2 3
Sample Output
4
题解:
先搞出g[i][j]表示i到j的运输花费,只是单个点,将f[i][i][0]先处理好,这个应该比较容易吧,
还有处理处f[i][fa[i]][0]的初始值,每一个父亲,就是整条链上所有父亲,什么意思,就是
一层一层更新上去。
处理出来的作为树形dp的初始化,然后就是dp
h1[k]表示在该点,建k个,该点建,的最小花费。
h2[k]表示在该点,建k个,该点不建,最小花费。
然后就dp在哪个子孙建多少个,的一个背包dp。
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<cstdlib>
#define N 107
#define M 57
using namespace std; int n,k;
int cnt,head[N],next[N*],rea[N*];
int fa[N],w[N],di[N],g[N][N];
int f[N][N][M];
bool vis[N][N][M]; void add(int u,int v){next[++cnt]=head[u],head[u]=cnt,rea[cnt]=v;}
void dfs_init(int u)
{
int t=u;
while(fa[t]>=)
{
g[u][fa[t]]=g[u][t]+w[u]*di[t];
t=fa[t];
}
t=u;
for (int i=head[u];i!=-;i=next[i])
{
int v=rea[i];
dfs_init(v);
w[u]+=w[v];
f[u][u][]+=f[v][u][];
}
vis[u][t][]=;
while(fa[t]>=)
{
vis[u][fa[t]][]=;
f[u][fa[t]][]=f[u][t][]+w[u]*di[t];
t=fa[t];
}
}
int solve_dp(int u,int now,int k)
{
if (vis[u][now][k]) return f[u][now][k];
vis[u][now][k]=;
int h1[],h2[];
memset(h1,,sizeof(h1));
for (int i=;i<=k;i++)
h2[i]=g[u][now];
for (int i=head[u];i!=-;i=next[i])
{
int v=rea[i];
for (int j=k;j>=;j--)
{
h1[j]+=solve_dp(v,u,);
h2[j]+=solve_dp(v,now,);
for (int t=;t<=j;t++)
{
h1[j]=min(h1[j],h1[j-t]+solve_dp(v,u,t));
h2[j]=min(h2[j],h2[j-t]+solve_dp(v,now,t));
}
}
}
f[u][now][k]=min(h1[k-],h2[k]);
return f[u][now][k];
}
int main()
{
memset(head,-,sizeof(head));
scanf("%d%d",&n,&k);
for (int i=;i<=n;i++)
{
scanf("%d%d%d",&w[i],&fa[i],&di[i]);
add(fa[i],i);
}
fa[]=-;
dfs_init();
printf("%d\n",solve_dp(,,k));
}
bzoj1812 [Ioi2005]riv的更多相关文章
- BZOJ1812: [Ioi2005]riv(树形dp)
题意 题目链接 Sol 首先一个很显然的思路是直接用\(f[i][j] / g[i][j]\)表示\(i\)的子树中选了\(j\)个节点,该节点是否选的最小权值.但是直接这样然后按照树形背包的套路转移 ...
- bzoj1812 [IOI2005]riv河流
题目链接 problem 给出一棵树,每个点有点权,每条边有边权.0号点为根,每个点的代价是这个点的点权\(\times\)该点到根路径上的边权和. 现在可以选择最多K个点.使得每个点的代价变为:这个 ...
- 【BZOJ1812】[Ioi2005]riv 树形DP
[BZOJ1812][Ioi2005]riv Description 几乎整个Byteland王国都被森林和河流所覆盖.小点的河汇聚到一起,形成了稍大点的河.就这样,所有的河水都汇聚并流进了一条大河, ...
- BZOJ 1812: [Ioi2005]riv( 树形dp )
树背包, 左儿子右兄弟来表示树, dp(x, y, z)表示结点x, x的子树及x的部分兄弟共建y个伐木场, 离x最近的伐木场是z时的最小代价. 时间复杂度O(N^2*K^2) ----------- ...
- 1812: [Ioi2005]riv
1812: [Ioi2005]riv Time Limit: 10 Sec Memory Limit: 64 MB Submit: 635 Solved: 388 [Submit][Status][D ...
- 【BZOJ1812】riv(多叉树转二叉树,树形DP)
题意:给定一棵树,每个点有权值,每条边有边权(单向边).你可以选取K个黑点,使得从每个点移动到距离他最近的黑点的花费(距离*点权)的总和最小. n<=100 k<=50 w[i],a[i] ...
- BZOJ1812 [IOI2005]river
传送门: 很常规的一道树规,转为左儿子右兄弟. 然后$f[node][anc][K]$表示在node节点上,最近的有贡献祖先在anc上,在node的儿子和兄弟上有k个有贡献节点的最优值. 然后得出以下 ...
- BZOJ.1812.[IOI2005]Riv 河流(树形背包)
BZOJ 洛谷 这个数据范围..考虑暴力一些把各种信息都记下来.不妨直接令\(f[i][j][k][0/1]\)表示当前为点\(i\),离\(i\)最近的建了伐木场的\(i\)的祖先为\(j\),\( ...
- P3354 [IOI2005]Riv 河流
树形dp,设f[i][j][k]表示第i个点的子树中选择j个点作为伐木场,而且k是建了伐木场的最浅的i的祖先的情况下,最小的收益. 这种题还要练一下,咕咕 然后转移可以n4方做. // luogu-j ...
随机推荐
- 201521123063 《Java程序设计》 第7周学习总结
1. 本周学习总结 以你喜欢的方式(思维导图或其他)归纳总结集合相关内容. 2. 书面作业 ArrayList代码分析 1.1 解释ArrayList的contains源代码 public boole ...
- 201521123056 《Java程序设计》第7周学习总结
1. 本周学习总结 2. 书面作业 1. ArrayList代码分析 1.1 解释ArrayList的contains源代码 1.2 解释E remove(int index)源代码 1.3 结合1. ...
- 201521123068《Java程序设计》第4周学习总结
1. 本周学习总结 1.1 尝试使用思维导图总结有关继承的知识点. 点击查看->高清脑图 1.2 使用常规方法总结其他上课内容. 答:学习继承与多态的知识,了解它们之间的关系:super.ext ...
- ★★★★[转载]Python学习笔记一:数据类型转换★★★★
一.int函数能够 (1)把符合数学格式的数字型字符串转换成整数 (2)把浮点数转换成整数,但是只是简单的取整,而非四舍五入. 举例: 1 aa = int("124&quo ...
- 201521123009 《Java程序设计》第12周学习总结
1. 本周学习总结 2. 书面作业 Q1:将Student对象(属性:int id, String name,int age,double grade)写入文件student.data.从文件读出显示 ...
- 201521123116 《java程序设计》第十三周学习总结
1. 本周学习总结 以你喜欢的方式(思维导图.OneNote或其他)归纳总结多网络相关内容. 2. 书面作业 Q1. 网络基础 1.1 比较ping www.baidu.com与ping cec.jm ...
- 201521123113《Java程序设计》第9周学习总结
1. 本周学习总结 2. 书面作业 本次PTA作业题集异常 Q1.常用异常 题目5-1 1.1 截图你的提交结果(出现学号) 1.2 自己以前编写的代码中经常出现什么异常.需要捕获吗(为什么)?应如何 ...
- 王者荣耀是怎样炼成的(二)《王者荣耀》unity安装及使用的小白零基础入门
转载请注明出处:http://www.cnblogs.com/yuxiuyan/p/7535345.html 工欲善其事,必先利其器. 上回书说到,开发游戏用到unity和C#.本篇博客将从零开始做一 ...
- ACM退役记&&回忆录
ACM退役记 2017.9.19星期二,"九一八事变"八十六年后的第二天,永远记住这个日子,刚好是我报名ACM到现在,刚好满一年,而今天正是我注册杭州电子科技大学OJ的时间(就是这 ...
- JavaScript中DOM
概念 什么是DOM 1. 什么是 DOM DOM 的全称是document object model 它的基本思想是将结构化文佳例如HTML xml解析成一系列的节点.就像一颗树一样. 所有的节点和最 ...