http://codeforces.com/contest/596/problem/D

题目大意:

有n棵树排成一排,高度都为h.

主人公要去砍树,每次等概率地随机选择没倒的树中最左边的树或者最右边的树把它砍倒.每棵树被砍到后,有p的概率会往左边倒,(1-p)的概率往右边倒.

树倒下后如果压到别的树,即如果那棵树倒下的方向上距离不到h的地方还有一棵树,,那么那棵树也会朝和这个树相同的方向倒下.

问最后所有的树都被砍完后覆盖的地面的长度的期望.

思路:dp[i][j][0/1][0/1]代表i到j这个区间,i-1的状态是0/1,j+1的状态是0/1的长度期望

我们每次只求当前倒下树增加的期望.

转移比较复杂:

当l=r时,判断有没有被左右某棵树压倒,有那就直接取这样做的贡献

否则我们要算上概率,p往左倒,1-p往右倒

当l不等于r时,我们有最左边和最右边的两棵树的选择,同样看一下有没有被外层的某棵树压倒,压倒就直接算,否则我们考虑往左和往右倒的概率,以及选最左边和最右边的概率。

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<iostream>
#define ll long long
ll a[];
bool vis[][][][];
double f[][][][];
int n;
ll h;
double p;
int read(){
int t=,f=;char ch=getchar();
while (ch<''||ch>''){if (ch=='-') f=-;ch=getchar();}
while (''<=ch&&ch<=''){t=t*+ch-'';ch=getchar();}
return t*f;
}
double dp(int l,int r,int sl,int sr){
if (vis[l][r][sl][sr]) return f[l][r][sl][sr];
vis[l][r][sl][sr]=;
f[l][r][sl][sr]=;
if (l==r){
if (sl==&&a[l-]+h>a[l]){
if (sr) return f[l][r][sl][sr]=std::min(h,a[l+]-a[l]);
else return f[l][r][sl][sr]=std::min(h,std::max(0LL,a[l+]-a[l]-h));
}else
if (sr==&&a[r+]-h<a[r]){
if (sl==) return f[l][r][sl][sr]=std::min(h,a[l]-a[l-]);
else return f[l][r][sl][sr]=std::min(h,std::max(0LL,a[l]-a[l-]-h));
}
double ans=;
if (sl)
ans+=p*std::min(h,std::max(0LL,a[l]-a[l-]-h));
else
ans+=p*std::min(h,a[l]-a[l-]);
if (sr==)
ans+=(1.0-p)*std::min(h,std::max(0LL,a[l+]-a[l]-h));
else
ans+=(1.0-p)*std::min(h,a[l+]-a[l]);
return f[l][r][sl][sr]=ans;
}
if (sl==&&a[l-]+h>a[l])
return f[l][r][sl][sr]=dp(l+,r,,sr)+std::min(h,a[l+]-a[l]);
else
if (sr==&&a[r+]-h<a[r])
return f[l][r][sl][sr]=dp(l,r-,sl,)+std::min(h,a[r]-a[r-]);
double ans=;
ans+=0.5*(-p)*(dp(l+,r,,sr)+std::min(h,a[l+]-a[l]));
ans+=0.5*(p)*(dp(l,r-,sl,)+std::min(a[r]-a[r-],h));
if (sl==)
ans+=0.5*p*(dp(l+,r,,sr)+std::min(h,std::max(0LL,a[l]-a[l-]-h)));
else
ans+=0.5*(p)*(dp(l+,r,,sr)+std::min(h,a[l]-a[l-])); if (sr==)
ans+=0.5*(-p)*(dp(l,r-,sl,)+std::min(h,std::max(0LL,a[r+]-a[r]-h)));
else
ans+=0.5*(-p)*(dp(l,r-,sl,)+std::min(h,a[r+]-a[r]));
return f[l][r][sl][sr]=ans;
}
int main(){
n=read();h=read();scanf("%lf",&p);
for (int i=;i<=n;i++) a[i]=read();
std::sort(a+,a++n);
a[]=a[]-1e10;a[n+]=a[n]+1e10;
printf("%.9f\n",dp(,n,,));
}

Codeforces 596D Wilbur and Trees的更多相关文章

  1. Codeforces 596D Wilbur and Trees dp (看题解)

    一直在考虑, 每一段的贡献, 没想到这个东西能直接dp..因为所有的h都是一样的. #include<bits/stdc++.h> #define LL long long #define ...

  2. Codeforces Round #331 (Div. 2) D. Wilbur and Trees 记忆化搜索

    D. Wilbur and Trees Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/596/p ...

  3. Codeforces 9D How many trees? 【计数类DP】

    Codeforces 9D How many trees? LINK 题目大意就是给你一个n和一个h 问你有多少个n个节点高度不小于h的二叉树 n和h的范围都很小 感觉有无限可能 考虑一下一个很显然的 ...

  4. Codeforces 545E. Paths and Trees 最短路

    E. Paths and Trees time limit per test: 3 seconds memory limit per test: 256 megabytes input: standa ...

  5. CodeForces #369 C. Coloring Trees DP

    题目链接:C. Coloring Trees 题意:给出n棵树的颜色,有些树被染了,有些没有.现在让你把没被染色的树染色.使得beauty = k.问,最少使用的颜料是多少.   K:连续的颜色为一组 ...

  6. codeforces 711C C. Coloring Trees(dp)

    题目链接: C. Coloring Trees time limit per test 2 seconds memory limit per test 256 megabytes input stan ...

  7. Codeforces 711 C. Coloring Trees (dp)

    题目链接:http://codeforces.com/problemset/problem/711/C 给你n棵树,m种颜色,k是指定最后的完美值.接下来一行n个数 表示1~n树原本的颜色,0的话就是 ...

  8. codeforces 633G. Yash And Trees dfs序+线段树+bitset

    题目链接 G. Yash And Trees time limit per test 4 seconds memory limit per test 512 megabytes input stand ...

  9. Codeforces - 9D - How many trees? - 简单dp - 组合数学

    https://codeforces.com/problemset/problem/9/D 一开始居然还想直接找公式的,想了想还是放弃了.原来这种结构是要动态规划. 状态是知道怎么设了,$t_{nh} ...

随机推荐

  1. centos6.5+Django+mysql+nginx+uwsgi

    centos6.5+Django+mysql+nginx+uwsgi 1.nginx的安装.这里采用nginx-1.6.0, 建立一个shell脚本然后执行. #!/bin/bash nginx_ve ...

  2. op编译信赖的库

    Table of known prerequisites and their corresponding packages Here's a table with the package name f ...

  3. POJ 1979 深度优先搜索

    题意:有红色和黑色的格子,只能走黑色的,问从起始位置出发,最多能走到达多少块黑色格子. 分析:相当于走迷宫,黑色格子是路,红色格子是墙,每次到达一个未到达过的格子时计数,原点也算是一个.每次可以走上下 ...

  4. erlang mnesia 数据库查询

    Mnesia是一个分布式数据库管理系统,适合于电信和其它需要持续运行和具备软实时特性的Erlang应用,越来越受关注和使用,但是目前Mnesia资料却不多,很多都只有官方的用户指南.下面的内容将着重说 ...

  5. JS~模拟表单在新窗口打开,避免广告拦截

    说起广告拦截,这应该是浏览器的一个特性,它会将window.open产生的窗口默认为一个广告,将它进行拦截,但有时,这不是我们所希望的,有时,我们就是需要它在客户端的浏览器上弹出一个新窗口,以展示数据 ...

  6. SurfaceView类透明背景设置

    将SurfaceView背景设置为透明,主要添加以下几句话就可以了: 在SurfaceView创建后设置一下下面的参数: setZOrderOnTop(true); getHolder().setFo ...

  7. 如何判断手机收有几张SIM卡

    //判断卡槽1中是不是有卡 boolean hasIccCard1 = MSimTelephonyManager.getDefault().hasIccCard(0); //判断卡槽2中是不是有卡 b ...

  8. Mybatis高级映射、动态SQL及获得自增主键

    一.动态SQL 相信大家在用mybatis操作数据库时时都会碰到一个问题,假如现在我们有一个关于作者的list authorList,需要根据authorList里已有的作者信息在数据库中查询相应作者 ...

  9. FoxOne---一个快速高效的BS框架

    FoxOne---一个快速高效的BS框架--(1) FoxOne---一个快速高效的BS框架--(2) FoxOne---一个快速高效的BS框架--(3) FoxOne---一个快速高效的BS框架-- ...

  10. 开发日志_Jan.9

    今天主要工作为修改昨天的碰撞引擎不符合预期的部分. 经过了昨天的工作,碰撞算法已经初见雏形.但是主要有两个问题: 碰撞反弹的方向与预期不符合 碰撞后球与机器人存在一个"黏在一起"的 ...