zoukankan      html  css  js  c++  java
  • BZOJ 1065 奥运物流

    http://www.lydsy.com/JudgeOnline/problem.php?id=1065

    思路:由于n个点,有n条边,因此由根就会引出一个环,我们枚举环的长度,在那个长度断开,我们假设len为环的长度。

    由于R(i)满足

    而产生环时,R[1]=Σci*k^di + R[1]*(k^len),得到

    R[1]=(Σci*k^di)/(1-k^len)

    因此我们枚举len,然后做树形DP,f[i][j][k]代表第i个点,修改了j次,当前深度为k

    那么最后的贡献是Σf[i][j][1],i为1的直接儿子,用一个01背包统计,最后答案就是(ans+c[1])/(1-k^len)

    有个蛋疼的地方就是做01背包的时候。。要注意循环变量的顺序,不要重复统计。。

     1 #include<algorithm>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<cstring>
     5 #include<iostream>
     6 int n,m,pre[200005];
     7 double K[200005],c[200005],f[80][80][80],g[80][80][80],F[200005];
     8 int read(){
     9     int t=0,f=1;char ch=getchar();
    10     while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
    11     while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();}
    12     return t*f;
    13 }
    14 void dp(int x,int dep){
    15     for (int i=2;i<=n;i++) if (pre[i]==x) dp(i,dep+1);
    16     for (int d=std::min(2,dep);d<=dep;d++){
    17          for (int j=0;j<=m;j++) F[j]=0;
    18          for (int i=2;i<=n;i++)
    19               if (pre[i]==x)
    20               for (int j=m;j>=0;j--)
    21                 for (int k=j;k>=0;k--)
    22                     F[j]=std::max(F[j],F[k]+g[i][j-k][d]);
    23         for (int i=0;i<=m;i++)
    24             f[x][i][d]=F[i]+c[x]*K[d];        
    25     }    
    26     if (dep>1){
    27         for (int i=0;i<=m;i++) F[i]=0;
    28         for (int i=2;i<=n;i++)
    29             if (pre[i]==x)
    30             for (int j=m;j>=0;j--)
    31                 for (int k=j;k>=0;k--)
    32                     F[j]=std::max(F[j],F[k]+g[i][j-k][1]);
    33         for (int i=1;i<=m;i++)
    34             f[x][i][1]=F[i-1]+c[x]*K[1];    
    35     }
    36     for (int j=0;j<=m;j++)
    37          for (int d=0;d<dep;d++)
    38             g[x][j][d]=std::max(f[x][j][d+1],f[x][j][1]);
    39 }
    40 int main(){
    41     n=read();m=read();scanf("%lf",&K[1]);
    42     for (int i=2;i<=n;i++) K[i]=K[i-1]*K[1];
    43     for (int i=1;i<=n;i++) pre[i]=read();
    44     for (int i=1;i<=n;i++) scanf("%lf",&c[i]);
    45     double ans=0;
    46     for (int I=pre[1],len=2;I-1;I=pre[I],len++){
    47         for (int i=1;i<=n;i++)
    48          for (int j=0;j<=m;j++)
    49            for (int k=0;k<=n;k++)
    50                f[i][j][k]=g[i][j][k]=0;
    51         int tmp=pre[I];pre[I]=1;   
    52         for (int i=2;i<=n;i++) if (pre[i]==1) dp(i,1);
    53         for (int i=0;i<=m;i++) F[i]=0;
    54         for (int i=2;i<=n;i++)
    55          if  (pre[i]==1)
    56             for (int j=m;j>=0;j--)
    57                  for (int k=j;k>=0;k--)
    58                    F[j]=std::max(F[j],F[k]+f[i][j-k][1]);
    59         double now=0;
    60         for (int i=0;i<m;i++) now=std::max(now,F[i]);    
    61         if (tmp==1) now=std::max(now,F[m]);
    62         pre[I]=tmp;
    63         ans=std::max(ans,(now+c[1])/(1-K[len]));    
    64     }
    65     printf("%.2lf
    ",ans);
    66 }
  • 相关阅读:
    20171130-构建之法:现代软件工程-阅读笔记
    软件工程课程总结
    团队编程项目作业6-程序维护
    团队-象棋游戏-项目总结
    20171117-构建之法:现代软件工程-阅读笔记
    团队-象棋游戏-团队一阶段互评
    课后作业-阅读任务-阅读笔记-1
    课后作业-阅读任务-阅读提问-1
    课后作业-阅读任务-阅读提问-2
    阿里云部署node坑
  • 原文地址:https://www.cnblogs.com/qzqzgfy/p/5594596.html
Copyright © 2011-2022 走看看