URAL1776-------用DP来求概率

题目地址:http://acm.timus.ru/problem.aspx?space=1&num=1776

题目意思:

有n个火箭给你发射

每次发射间隔为10s

第一次,即第0s发射1,n

然后在发射其它的

每次只要处在已经发射火箭的中间的都可以发射,也就是可以同时发射多个

要你求期望

题目思路:

首先申明这份代码其实是参考的http://www.nocow.cn/index.php/%E9%A6%96%E9%A1%B5   ZZY的代码

我们用f[i][j]来表示发射i个火箭需要j个10s的概率

用s[i][j]来表示发射i个火箭需要<=j个10s的概率

即s[i][j] = sum(f[i][k]) 1<=k<=j

那么对于一个f[i][j]来说,我们怎么求呢

我们可以枚举1~i之间的某个点作为最后一个被发射的火箭

那么他的概率就是左边的j-1个以及右边的i-j个都被发射之后再发射他的的概率

不仅如此,再计算概率的时候,我们还要枚举发射发射火箭用了多久的时间

即可以枚举1到某个数t,最会的情况就是n

事实上,我们可以令l=j-1,r=i-j代表位于j左右两边已经发射的火箭个数,那么前面最多耗的时间也就是max(l,r)+1

为什么要加1呢?因为还有我们再j这个位置发射的时间

PS:我们用的都是单位时间,最后再*10就OK

我们令k表示本次花费的时间

得到如下的代码:

for(int i=1;i
其中公式:

f[i][k] += (f[l][k-1]*s[r][k-1]+f[r][k-1]*s[l][k-1]-f[l][k-1]*f[r][k-1])/i;

的意思是发射左边的l个火箭用了k-1个乘以右边发射r个花费小于等于k-1单位时间的概率,

以及发射右边r个火箭花费了k-1个时间乘以左边发射l个花费小于等于k-1个单位时间的概率

-f[l][k-1]*f[r][k-1]是什么呢?我们之前提到s[i][j] = sum(f[i][k]) 1<=k<=j

所以在上面进行:

f[i][k] += (f[l][k-1]*s[r][k-1]+f[r][k-1]*s[l][k-1]-f[l][k-1]*f[r][k-1])/i;的时候我们实际上多计算了一个f[l][k-1]*f[r][k-1]

所以要减去,至于后面的/i就是本次的概率

然后再用

for(int j=1;j
来更新s[i][j]

在本题中我还使用了打表的方法,稍微提高了程序的效率

下面上代码:

#include
#include
#include
using namespace std;

const int maxn = 401;

double f[maxn][maxn];
double s[maxn][maxn];

int main()
{
    memset(f,0,sizeof(f));
    memset(s,0,sizeof(s));
    f[0][0]=1.0;
    for(int i=0;i

感谢ZZY的代码共享。

你可能感兴趣的:(动态规划)