cf596d
题意:有一排等高的树木,高度都为h。给出每棵树在数轴上的坐标,每次有可能是最左边或者最右边的立着的树倒下,概率都是0.5。最终所有树都倒下。每棵树在倒下的时候有p的概率向左倒,1-p的概率向右倒。如果某些树之间的距离小于h,那么倒下的时候可能产生连带效应。问最后所有树都倒下时,在数轴上覆盖的线段的总长度是多少。
分析:
概率DP求期望:
我们以前学过的求期望的方法是每种结果出现的概率乘以每种结果的值,然后相加。但是通常解决这类问题我们都要对每个中间状态求期望值,最终算出总的期望。这时我们就可以把每个状态的后继状态(子问题)看成是一个结果值,而不是期望值。
如果是算期望通常需要逆向思维E(u)=sigma(pv*E(v)+C),其中C是状态u和状态v之间的期望差值,pv是u状态转移到v状态的概率。v是u拆分后的子问题。
注意:sigma(pv)=1
本题我们开一个数组叫f[l][r][a][b]。
表示现在从l到r的树还立着,a=0表示l-1树向左倒的,a=1表示其向右倒的。b同理描述了r+1树的倒法。
我们下面来看它的一个后继状态,l向左倒。
f[l][r][a][b]+= 0.5 * p * (f[l+1][r][0][b] + l向左倒下时覆盖长度的增量)。
注意处理一些特殊情况,例如连带倒下,有可能需要将l+1换成right_most[l]表示最远能倒到哪棵。覆盖长度增量也要注意处理一次性所有树都倒下了的情况。
其他状态转移的话用同样方法再加上l向右,r向左向右倒的状态就行了。
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std; #define d(x) const int INF = 0x3f3f3f3f;
const int MAX_N = ; int n, h;
double p;
int pos[MAX_N];
double f[MAX_N][MAX_N][][];
int left_most[MAX_N];
int right_most[MAX_N]; void input()
{
scanf("%d%d%lf", &n, &h, &p);
for (int i = ; i < n; i++)
{
scanf("%d", &pos[i]);
}
} int get_pos(int a)
{
if (a < )
return -INF;
if (a >= n)
return INF;
return pos[a];
} int get_dist(int a, int b)
{
return get_pos(b) - get_pos(a);
} int get_increment_left(int i, int a)
{
return min(h, get_dist(i - , i) - h * a);
} int get_increment_right(int i, int b)
{
return min(h, get_dist(i, i + ) - h * ( - b));
} double cal(int l, int r, int a, int b)
{
double ret = ;
int temp1 = ;
int temp2 = ;
int temp = ; ret += 0.5 * p * (get_increment_left(l, a) + f[l + ][r][][b]); ret += 0.5 * ( - p) * (get_increment_right(r, b) + f[l][r - ][a][]); temp1 = get_dist(l, right_most[l]) + h;
temp2 = get_dist(l, r + ) - ( - b) * h;
temp = min(temp1, temp2);
ret += 0.5 * ( - p) * (temp + f[right_most[l] + ][r][][b]); temp1 = get_dist(left_most[r], r) + h;
temp2 = get_dist(l - , r) - a * h;
temp = min(temp1, temp2);
ret += 0.5 * p * (temp + f[l][left_most[r] - ][a][]); return ret;
} void cal(int l, int r)
{
for (int a = ; a < ; a++)
{
for (int b = ; b < ; b++)
{
if (a == && get_dist(l - , l) < h)
continue;
if (b == && get_dist(r, r + ) < h)
continue;
f[l][r][a][b] = cal(l, r, a, b);
d(printf("f[%d][%d][%d][%d]=%.3f\n", l, r, a, b, f[l][r][a][b]));
}
}
} double work()
{
memset(f, , sizeof(f));
for (int i = ; i < n; i++)
{
for (int a = ; a < ; a++)
{
for (int b = ; b < ; b++)
{
if (a == && get_dist(i - , i) < h)
continue;
if (b == && get_dist(i, i + ) < h)
continue;
//the value of a and b: 0 left, 1 right
f[i][i][a][b] = p * get_increment_left(i, a);
f[i][i][a][b] += ( - p) * get_increment_right(i, b);
d(printf("f[%d][%d][%d][%d]=%.3f\n", i, i, a, b, f[i][i][a][b]));
}
}
} for (int len = ; len < n; len++)
{
for (int i = ; i + len < n; i++)
{
int l = i;
int r = i + len;
cal(l, r);
}
}
return f[][n - ][][];
} void make()
{
for (int i = ; i < n; i++)
{
if (get_dist(i - , i) < h)
left_most[i] = left_most[i - ];
else
left_most[i] = i;
}
for (int i = n - ; i >= ; i--)
{
if (get_dist(i, i + ) < h)
right_most[i] = right_most[i + ];
else
right_most[i] = i;
}
} int main()
{
input();
sort(pos, pos + n);
make();
printf("%.9f\n", work());
return ;
}
cf596d的更多相关文章
- CF596D Wilbur and Trees
题意:有一些高度为h的树在数轴上.每次选择剩下的树中最左边或是最右边的树推倒(各50%概率),往左倒有p的概率,往右倒1-p. 一棵树倒了,如果挨到的另一棵树与该数的距离严格小于h,那么它也会往同方向 ...
随机推荐
- 2748: [HAOI2012]音量调节 bzoj
Description 一个吉他手准备参加一场演出.他不喜欢在演出时始终使用同一个音量,所以他决定每一首歌之前他都要改变一次音量.在演出开始之前,他已经做好了一个列表,里面写着在每首歌开始之前他想要改 ...
- 老生长谈:css实现右侧固定宽度,左侧宽度自适应
反过来也可以:左侧宽度固定,右侧自适应.不管是左是右,反正就是一边宽度固定,一边宽度自适应. 这种布局比较常见,博客园很多默认主题就是这种.一般情况下,这种布局中宽度固定的区域是侧边栏,而自适应的区域 ...
- js 运算符
一.算术运算符: 1.运算符: “+”:功能:对数字进行代数求和:对字符串进行连接操作:将一个数值转换为字符串(数值+空字符串). “-”:功能:对操作数进行取反操作:对数字进行减法操作:将字符串转换 ...
- 福利到~分享一个基于jquery的智能提示控件intellSeach.js
一.需求 我们经常会遇到[站内搜索]的需求,为了提高用户体验,我们希望能做到像百度那样的即时智能提示.例如:某公司人事管理系统,想搜索李XX,只要输入“李”,系统自然会提示一些姓李的员工,这样方便用户 ...
- RecyclerView的使用(四)
前面我们已经实现了RecyclerView的大部分功能了,但是有个很明显的缺陷-------没有点击效果!这就坑爹了 ListView自带点击效果好嘛!连这个都要自己定义.... 话不多说,下面就来为 ...
- 第二次团队作业——预则立&&他山之石
Deadline: 2016.10.16 22:00pm 一.确立团队选题,建立和初步熟悉团队git的协作方式.项目后续的代码.文档都要通过github增量式管理.实现文档的版本化和增量式管理. 二. ...
- Could not execute action
2.Could not execute action 原因:action成员变量有空值,要访问方法中,使用了该成员变量 参考: http://www.blogjava.net/javagrass/ar ...
- Microsoft.AspNet.Identity 自定义使用现有的表—登录实现
Microsoft.AspNet.Identity是微软新引入的一种membership框架,也是微软Owin标准的一个实现.Microsoft.AspNet.Identity.EntityFrame ...
- Mysql 命令大全
1.连接Mysql 格式: mysql -h主机地址 -u用户名 -p用户密码1.连接到本机上的MYSQL.首先打开DOS窗口,然后进入目录mysql\bin,再键入命令mysql -u root - ...
- BZOJ 3809: Gty的二逼妹子序列
3809: Gty的二逼妹子序列 Time Limit: 80 Sec Memory Limit: 28 MBSubmit: 1387 Solved: 400[Submit][Status][Di ...