csuoj2105Front Nine 概率期望dp

思路分析:用个二维数组记录每个点右边所包含面积的期望值,然后从后往前一个个递推即可。另一个方法是从前往后计算出到达每个点的概率,然后按期望的定义将前一个和后一个点概率的乘积再乘上这两点间的面积即可。

代码:

   从后往前递推期望

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
double dp[100010][110];    //这里dp数组记录从后往前点包含面积的期望
int main(){
    int i,j,n,h,a,p1,p2,p3;
    while(cin>>n>>h>>a>>p1>>p2>>p3){
        double c1,c2,c3;
        c1=p1*0.01;
        c2=p2*0.01;
        c3=p3*0.01;
        memset(dp,0,sizeof(dp));
        for(i=n;i>=1;i--){
            for(j=h;j>=0;j--){
                int x=j+1;
                if(x>h) x=h;
                dp[i][j]+=(dp[i+1][x]+(j+x)/2.0)*c3;
                x=j;
                dp[i][j]+=(dp[i+1][x]+(j+x)/2.0)*c2;
                x=j-1;
                if(x<0) x=0;
                dp[i][j]+=(dp[i+1][x]+(j+x)/2.0)*c1;
            }
        }
        printf("%.10f\n",dp[1][a]);
    }
    return 0;
}

从前往后计算概率

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
double dp[100010][110];  //这里dp数组记录的是到达每个点的概率
int main(){
    int n,x,h,i,j,a,b,c;
    double p1,p2,p3;
    while(scanf("%d%d%d%d%d%d",&n,&h,&x,&a,&b,&c)!=EOF){
        p1=a*0.01;
        p2=b*0.01;
        p3=c*0.01;
        memset(dp,0,sizeof(dp));
        dp[1][x]=1;
        double sum=0;
        for(i=1;i<=n;i++){
            for(j=0;j<=h;j++){
                    if(dp[i][j]!=0){
                         a=j-1;          //上中下三种情况,计算下一个点,同时计算面积期望
                         if(a<0) a=0;
                         dp[i+1][a]+=dp[i][j]*p1;
                         sum+=dp[i][j]*p1*(j+a)/2;
                         a=j;
                         dp[i+1][a]+=dp[i][j]*p2;
                         sum+=dp[i][j]*p2*(j+a)/2;
                         a=j+1;
                         if(a>h) a=h;
                         dp[i+1][a]+=dp[i][j]*p3;
                         sum+=dp[i][j]*p3*(j+a)/2;
                    }
            }
        }
        printf("%.10f\n",sum);
    }
    return 0;
}


猜你喜欢

转载自blog.csdn.net/guogai13/article/details/80458547