zoukankan      html  css  js  c++  java
  • BZOJ 1812 IOI 2005 riv

    1812: [Ioi2005]riv

    Time Limit: 10 Sec  Memory Limit: 64 MB
    Submit: 566  Solved: 335
    [Submit][Status][Discuss]

    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

    HINT

     

    Source

    这是一道树形dp题目

    首先转化为左儿子右兄弟的表示方法

    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[bro[node]][anc][K−1−k]}                                             有贡献

    代码如下

    #include <bits/stdc++.h>
    using namespace std;
    inline int read(){
     int x=0;int f=1;char ch=getchar();
     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
     return x*f;
    }
    const int MAXN=500;
    namespace zhangenming{
     struct node{
      int y,v,next;
     }e[MAXN];
     int linkk[MAXN],fa[MAXN],bra[MAXN],dis[MAXN],pre_fa[MAXN],son[MAXN],value[MAXN],N,K,len=0;
     int  f[110][110][110];
     inline void insert(int xx,int yy,int vv){
      e[++len].y=yy;e[len].next=linkk[xx];e[len].v=vv;linkk[xx]=len;
     }
     void dfs(int node){
      for(int i=linkk[node];i;i=e[i].next){
       dis[e[i].y]=dis[node]+e[i].v;
       dfs(e[i].y);
      }
     }
     void build(int father,int node){
      int tmp=linkk[node];fa[node]=father;son[node]=e[tmp].y;
      if(tmp) build(node,e[tmp].y);
      node=e[tmp].y;
      for(int i=e[tmp].next;i;i=e[i].next){
       bra[node]=e[i].y;
       build(node,e[i].y);
       node=e[i].y;
      }
     }
     void init(){
      N=read();K=read();
      for(int i=1;i<=N;i++){
       value[i]=read();
       int xx=read();
       int yy=read();
       insert(xx,i,yy);
       pre_fa[i]=xx;
      }
      pre_fa[0]=-1;
      dfs(0);
      dis[0]=0;
      build(-1,0);
     }
     void tree_dp(int node){
      if(son[node]){
       tree_dp(son[node]);
      }
      if(bra[node]){
       tree_dp(bra[node]);
      }
      int father=pre_fa[node];
      while(father!=-1){
       for(int i=0;i<=K;i++){
        for(int j=0;j<=i;j++){
         int tmp=(dis[node]-dis[father])*value[node];
         if(son[node]) tmp+=f[son[node]][father][j];
         if(bra[node]) tmp+=f[bra[node]][father][i-j];
         f[node][father][i]=min(f[node][father][i],tmp);
        }
       }
       for(int i=1;i<=K;i++){
        for(int j=1;j<=i;j++){
         int tmp=0;
         if(son[node]) tmp+=f[son[node]][node][j-1];
         if(bra[node]) tmp+=f[bra[node]][father][i-j];
         f[node][father][i]=min(f[node][father][i],tmp);
        }
       }
       father=pre_fa[father];
      }
      if(node==0){
       father=0;
       for(int i=0;i<=K;i++){
        for(int j=0;j<=i;j++){
        int tmp=0;
        if(son[node])tmp+=f[son[node]][father][j];
        if(bra[node])tmp+=f[bra[node]][father][i-j];
        f[node][father][i]=min(f[node][father][i],tmp);
        }
       }
      }
     }
     void solve(){
      memset(f,10,sizeof(f));
      tree_dp(0);
      cout<<f[0][0][K]<<endl;
     }
    }
    int main(){
     using namespace zhangenming;
     init();
     solve();
     return 0;
    }

    细节参考代码

  • 相关阅读:
    【题解】P2262 [HNOI2004]FTP服务器
    关于大模拟
    CodeForces 666E Forensic Examination
    Bzoj3233 [Ahoi2013]找硬币
    Bzoj4350 括号序列再战猪猪侠
    UOJ#31 【UR #2】猪猪侠再战括号序列
    UOJ#21 【UR #1】缩进优化
    51nod1667 概率好题
    [CodeChef
    51nod1245 Binomial Coefficients Revenge
  • 原文地址:https://www.cnblogs.com/something-for-nothing/p/7805930.html
Copyright © 2011-2022 走看看