zoukankan      html  css  js  c++  java
  • 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,23……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 }
  • 相关阅读:
    java的继承---包装器与自动装箱
    linux开机启动过程,很多人说的不太清楚的看看。
    黑盒测试/三角形(OC)
    git 忽略一些文件的提交
    volley 框架的使用
    如何通过阿里百川的集成,以及manifest的权限配置完成淘客商品详情页的链接
    抓取网站访问者的QQ号码
    写写东西吧
    Android 强制实现下线功能
    Android 新闻显示界面且适应平板
  • 原文地址:https://www.cnblogs.com/12mango/p/7237018.html
Copyright © 2011-2022 走看看