IOI 2005/bzoj 1812:riv 河流

Description

几乎整个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

题目

   芒果君:人生中第一道IOI的题,看到来源我就蒙b了,看完题目我更蒙b了。对于树形DP,有一种便于操作的处理方式,叫做孩子父亲表示法,它可以将多叉树转化成二叉树,结点的左结点储存它的大儿子,右结点储存它的大弟弟,使得信息的传递变有序了。之后将两点距转成点到根的前缀和。由于要计算距离,这次的dp方程需要有三维,第三维是最近的伐木场(不一定是父节点哦)。考虑时间选择记忆化搜索,状态分建不建两种,不建,从0到容量;建,从0到容量减1,递归时将k变成i,最后输出f[0][m][0]。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<cstring>
 5 #define inf 1<<29
 6 using namespace std;
 7 int hl[300],n,m,f[110][110][110],cnt,dis[110],lson[110],rson[110],val[110];
 8 struct X{
 9     int u,v,ne,w,len;
10 }e[10010];
11 void add(int u,int v,int w)
12 {
13     e[++cnt].u=u;
14     e[cnt].v=v;
15     e[cnt].w=w;
16     e[cnt].ne=hl[u];
17     hl[u]=cnt;
18 }
19 void build(int x)
20 {
21     int t;
22     for(int i=hl[x];i;i=e[i].ne) build(e[i].v);
23     for(int i=hl[x];i;i=e[i].ne){
24         int v=e[i].v;
25         if(!lson[x]) lson[x]=t=v;
26         else{
27             rson[t]=v;
28             t=v;
29         }
30     }
31 }
32 void finddis(int x,int y)
33 {
34     for(int i=hl[x];i;i=e[i].ne){
35         int v=e[i].v,w=e[i].w;
36         if(v==y) continue;
37         dis[v]=dis[x]+w;
38         finddis(v,x);
39     }
40 }
41 int dp(int i,int j,int k)
42 {
43     if(f[i][j][k]!=-1) return f[i][j][k];
44     f[i][j][k]=inf;
45     for(int t=0;t<=j;++t){
46         int tmp=0;
47         if(lson[i]) tmp+=dp(lson[i],t,k);
48         if(rson[i]) tmp+=dp(rson[i],j-t,k);
49         f[i][j][k]=min(f[i][j][k],tmp+(dis[i]-dis[k])*val[i]);
50     }
51     for(int t=0;t<j;++t){
52         int tmp=0;
53         if(lson[i]) tmp+=dp(lson[i],t,i);
54         if(rson[i]) tmp+=dp(rson[i],j-t-1,k);
55         f[i][j][k]=min(f[i][j][k],tmp);
56     }
57     return f[i][j][k];
58 }
59 int main()
60 {
61     int x,y,w;
62     scanf("%d%d",&n,&m);
63     for(int i=1;i<=n;++i){
64         scanf("%d%d%d",&w,&x,&y);
65         val[i]=w;
66         add(x,i,y);
67     }
68     build(0);
69     finddis(0,0);
70     memset(f,-1,sizeof(f));
71     printf("%d",dp(0,m,0));
72     return 0;
73 }
时间: 2024-08-24 13:09:32

IOI 2005/bzoj 1812:riv 河流的相关文章

BZOJ 1811 IOI 2005 mea 乱搞

题目大意:给出一个序列中相邻两个的平均值,问有多少个序列可以满足这个性质. 思路:不难看出,只要确定了任意一个数字,整个序列就是确定的.我们设第一个值为k,那么后面的值都可以用表达式表示.然后做一下差分,保证每一项>0,就可以确定k的范围,每一个k值对应一个序列. CODE: #define _CRT_SECURE_NO_DEPRECATE #include <cmath> #include <cstdio> #include <cstring> #include

[IOI2005]Riv 河流

题目描述 几乎整个Byteland 王国都被森林和河流所覆盖.小点的河汇聚到一起,形成了稍大点的河.就这样,所有的河水都汇聚并流进了一条大河,最后这条大河流进了大海.这条大河的入海口处有一个村庄--Bytetown.在Byteland国,有n个伐木的村庄,这些村庄都座落在河边.目前在Bytetown,有一个巨大的伐木场,它处理着全国砍下的所有木料.木料被砍下后,顺着河流而被运到Bytetown的伐木场.Byteland 的国王决定,为了减少运输木料的费用,再额外地建造k个伐木场.这k个伐木场将被

[HAOI 2005][BZOJ 1054] 移动玩具

先贴一波题面 1054: [HAOI2008]移动玩具 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2288  Solved: 1270 Description 在一个4*4的方框内摆放了若干个相同的玩具,某人想将这些玩具重新摆放成为他心中理想的状态,规定移动 时只能将玩具向上下左右四个方向移动,并且移动的位置不能有玩具,请你用最少的移动次数将初始的玩具状态移 动到某人心中的目标状态. Input 前4行表示玩具的初始状态,每行4个数字1或0,

【题解】互不侵犯 SCOI 2005 BZOJ 1087 插头dp

以前没学插头dp的时候觉得这题贼难,根本不会做,学了才发现原来是一裸题. 用二进制表示以前的格子的状态,0表示没放国王,1表示放了国王. 假设当前位置为(x,y),需要记录的是(x-1,y-1)至(x,y-1)的信息,共n+1个点. 每个状态有两种决策,第一种是这个格子不放国王,直接转移. 第二种是这个格子放国王,需要满足几个条件才能进行这步转移,条件很显然,具体见代码和注释. 因为状态数很少,所以也用不到BFS转移状态和Hash的技巧,所以这题还是很清真的,细节不多,码量也很小. #inclu

bzoj1812 [IOI2005]riv河流

题目链接 problem 给出一棵树,每个点有点权,每条边有边权.0号点为根,每个点的代价是这个点的点权\(\times\)该点到根路径上的边权和. 现在可以选择最多K个点.使得每个点的代价变为:这个点的点权\(\times\)改点到最近的被选中的一个祖先的边权和. 问所有点的代价和最小为多少. solution 用\(g[i][j]\)表示以i为根的子树,强制选i,最大的贡献(这里的贡献是指比什么也不选所减少的代价.) 最终答案肯定就是初始代价-g[0][k] 考虑怎么维护出\(g\).用\(

优质题表(机密版)

转载请注明出处:http://www.cnblogs.com/dashuzhilin/p/4556803.html 思维题: poj 1528 poj 1597 poj 2538 poj 2608 poj 2612 poj 2361 poj 2339 poj 2664 uva 10894 uva 10921   uva 10922   uva 10929 uva 10931   uva 10800   uva 10878 uva 10976   uva 10323   uva 201 poj 2

BZOJ1812 [IOI2005]river

传送门: 很常规的一道树规,转为左儿子右兄弟. 然后f[node][anc][K]表示在node节点上,最近的有贡献祖先在anc上,在node的儿子和兄弟上有k个有贡献节点的最优值. 然后得出以下转移方程. f[node][anc][K]=min{f[son[node]][anc][k]+f[bro[node]][anc][K-k]}+Value[node]*(dis[node]-dis[anc]); 无贡献 f[node][anc][K]=min{f[son[node]][node][k]+f

河流(2005 IOI)

题目 第一步 复杂度分析 由于 n 的级别是100的,所以可以往O(n^3)上面想,数组可以开到三维. 第二步 类比 类比普通的树龟,我们通常设F[i][j]表示在以 i 为根的子树上选取 j 个结点的最优解.但这道题并不同于普通的树龟.所以需要寻找它与普通树龟的根本差别. 可以发现这道题多了一个DP影响因素:结点 i 上方的伐木场.由于 i 上方的伐木场是不确定的,因此设F[i][j]有后效性. 第三步 化繁为简 既然 i 上方的伐木场会影响DP的值,我们就把它加入维度,该结点称为'相对祖先'

1812: [Ioi2005]riv

1812: [Ioi2005]riv Time Limit: 10 Sec Memory Limit: 64 MB Submit: 635 Solved: 388 [Submit][Status][Discuss] Description 几乎整个Byteland王国都被森林和河流所覆盖.小点的河汇聚到一起,形成了稍大点的河.就这样,所有的河水都汇聚并流进了一条大河,最后这条大河流进了大海.这条大河的入海口处有一个村庄--名叫Bytetown 在Byteland国,有n个伐木的村庄,这些村庄都座