【专题】概率dp求期望

求期望两种题型。

1.概率dp

2.高斯消元

这里有一篇很好的文章:http://kicd.blog.163.com/blog/static/126961911200910168335852/

还有kb大神的专题:http://www.cnblogs.com/kuangbin/archive/2012/10/02/2710606.html

然后是我AC的三道小题。全部是概率dp

poj-2096

dp[i][j]代表i,j到n,s的期望步数;

(i*(s-j)/(n*s))*dp[i][j+1]中,i/(n*s)代表在i中取一个的概率,(s-j)/(n*s)代表在s-j中取一个,放到j+1中的概率.dp[i][j+1]同时还代表取到i个n及j+1个s的状态。

'='代表dp[i][j]前一步的所有期望步数*概率的和+1步。

View Code
#include <iostream>
#include <stdio.h>
using namespace std;
#define N 1005
#define S 1005
double dp[N][S];
int main()
{
    int n,s;
    while(scanf("%d%d",&n,&s)!=EOF){
        //for(int i=0;i<=n;i++)
            //for(int j=0;j<=s;j++)
                dp[n][s]=0;
        for(int i=n;i>=0;i--)
            for(int j=s;j>=0;j--)
                if(i==n && j==s) continue;
                else dp[i][j]=(i*(s-j)*dp[i][j+1]+(n-i)*j*dp[i+1][j]+(n-i)*(s-j)*dp[i+1][j+1]+n*s)/(n*s-i*j);
        printf("%.4f\n",dp[0][0]);
    }
    return 0;
}

hdu-4405

View Code
#include <iostream>
#include <string.h>
#include <stdio.h>
#define V 100005
#define E 1005
using namespace std;
struct Edge{
    int u,v,next;
}edge[E];
int head[V],cnt;
void init(){
    cnt=0;
    memset(head,-1,sizeof(head));
}
void addedge(int u,int v){
    edge[cnt].u=u;
    edge[cnt].v=v;
    edge[cnt].next=head[u];
    head[u]=cnt++;
}
int n,m,a,b;
bool vis[V];
double  dp[V];
int main()
{
    while(scanf("%d%d",&n,&m)!=EOF){
        if(n==0 && m==0) break;
        init();
        memset(dp,0,sizeof(dp));
        memset(vis,0,sizeof(vis));
        while(m--){
           scanf("%d%d",&a,&b);
           addedge(b,a);
        }
        dp[n]=-1;//想走到自己,需要-1步
        for(int i=n;i>=0;i--){
            if(!vis[i]){
                dp[i]+=(dp[i+1]+dp[i+2]+dp[i+3]+dp[i+4]+dp[i+5]+dp[i+6])/6.0+1.0;
                vis[i]=1;
            }
            for(int j=head[i];j!=-1;j=edge[j].next){
                dp[edge[j].v]=dp[i];
                vis[edge[j].v]=true;
            }
        }
        //for(int i=0;i<=n;i++) cout << dp[i] <<endl;
        printf("%.4lf\n",dp[0]);
    }
    return 0;
}

hdu-3853

View Code
#include <math.h>
#include <stdlib.h>
#include <iostream>
#include <stdio.h>
#include <string.h>
#define R 1005
#define C 1005
const double eps=1e-5;
using namespace std;
double dp[R][C];
int r,c;
struct P{
    double x,y,z;
}p[R][C];
int main()
{
    //freopen("in.txt","r",stdin);
    while(scanf("%d%d",&r,&c)!=EOF){
        for(int i=1;i<=r;i++){
            for(int j=1;j<=c;j++){
                scanf("%lf%lf%lf",&p[i][j].x,&p[i][j].y,&p[i][j].z);
            }
        }
        memset(dp,0,sizeof(dp));

        dp[r][c]=0;
        for(int i=r;i>=1;i--){
            for(int j=c;j>=1;j--){
                if(i==r && j==c) continue;
                if(fabs(1-p[i][j].x)<eps) continue;
                dp[i][j]=(p[i][j].y*dp[i][j+1]+p[i][j].z*dp[i+1][j]+2.0)/(1.0-p[i][j].x);
            }
        }
        /*for(int i=1;i<=r;i++){
            for(int j=1;j<=c;j++){
                printf("%.3lf ",dp[i][j]);
            }
            printf("\n");
        }*/
        printf("%.3lf\n",dp[1][1]);
    }
    return 0;
}

剑指杭州。

原文地址:https://www.cnblogs.com/markliu/p/2743770.html