bzoj 2784 时间流逝 —— 树上高斯消元

Posted zinn

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 2784 时间流逝 —— 树上高斯消元相关的知识,希望对你有一定的参考价值。

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2784

其实转移是一棵树,从根到一个点表示一种能量圈状态,当能量值大于 T 是停止,也就是成为叶子;

点数大约是整数划分,据说是 1.2e6 左右,可以 dfs;

设 ( d[x] ) 是儿子数,则 ( f[x] = p*(f[fa]+1) + (1-p) frac{sumlimits_{v in son}(f[v]+1)}{d[x]} )

仍然设 ( f[x] = K[x] * f[fa] + B[x] ),得到 ( K[x] = frac{d[x]*p}{d[x]-(1-p) sum A[v] } , B[x] = frac{(1-p)sum B[v] + d[x]}{d[x]-(1-p) sum A[v]} )

走到叶子停止,而叶子的值本来就是 0,所以直接做即可;

注意根的 ( p ) 不同,直接在根处把 ( p ) 改成 0 即可。

代码如下:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef double db;
int rd()
{
  int ret=0,f=1; char ch=getchar();
  while(ch<0||ch>9){if(ch==-)f=0; ch=getchar();}
  while(ch>=0&&ch<=9)ret=ret*10+ch-0,ch=getchar();
  return f?ret:-ret;
}
int T,n,w[35]; db p;
struct N{
  db K,B;
  N(db k=0,db b=0):K(k),B(b) {}
};
N dfs(int sum,int d)
{
  if(sum>T)return N(0,0);
  db ks=0,bs=0,P=(sum==0?0:p);
  for(int i=1;i<=d;i++)
    {
      N tmp=dfs(sum+w[i],i);
      ks+=tmp.K; bs+=tmp.B;
    }
  return N(d*P/(d-(1-P)*ks),((1-P)*bs+d)/(d-(1-P)*ks));
}
int main()
{
  while(~scanf("%lf",&p))
    {
      T=rd(); n=rd();
      for(int i=1;i<=n;i++)w[i]=rd();
      sort(w+1,w+n+1);
      printf("%.3f
",dfs(0,n).B);
    }
  return 0;
}

 

以上是关于bzoj 2784 时间流逝 —— 树上高斯消元的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ2784[JLOI2012]时间流逝

bzoj 2784: [JLOI2012]时间流逝树形期望dp

BZOJ 2466 中山市选2009 树 高斯消元+暴力

CF802L Send the Fool Further! (hard) 树上高斯消元

bzoj1013高斯消元

bzoj 3270 博物馆 高斯消元