概率DP入门题

关键在于找递推关系

POJ2096
题意:
一个软件有s个子系统,会产生n种bug
一个人每天发现一个bug,这个bug属于一个子系统,属于一种分类
每个bug属于某个子系统的概率是1/s,属于某种分类的概率是1/n
问发现n种bug,每个子系统都发现bug的天数的期望。
递推式:
dp[i][j]表示发现i个bug输入j个子系统的期望:
dp[i][j]= i/n * j/s dp[i][j] + i/n (s-j)/s dp[i+1][j] +(n-i)j/sdp[i+!][j] + (n-i)/n (s-j)/s *dp[i+1][j] +1

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define mod 1000000007
typedef long long ll;
double dp[1005][1005];
int main(){
 int n,s;
 while(scanf("%d%d",&n,&s)!=EOF){
  dp[n][s]=0;
  for(int i=n;i>=0;i--){
   for(int j=s;j>=0;j--){
    if(i==n&&j==s) continue;
    dp[i][j] = (n*s+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-i*j);
   }
  }
  printf("%.4f\n",dp[0][0]);
 }
 return 0;
}

HDU 4405

题意:在一个1×n的格子上掷色子,从0点出发,掷了多少前进几步,同时有些格点直接相连,即若a,b相连,当落到a点时直接飞向b点。求走到n或超出n期望掷色子次数

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define mod 1000000007
typedef long long ll;
double dp[100005];
int id[100005];
int main(){
 int n,s;
 while(scanf("%d%d",&n,&s)!=EOF){
  if(n==0&s==0)  break;
  memset(id,0,sizeof(id));
  memset(dp,0,sizeof(dp));
  for(int i=1;i<=s;i++){
   int x,y;
   scanf("%d%d",&x,&y);
   id[x]=y;
  }
  for(int i=n-1;i>=0;i--){
   if(id[i]!=0) dp[i]=dp[id[i]];
   else{
    for(int j=1;j<=6;j++)
     dp[i]+=dp[i+j]/6.0;
    dp[i]+=1;
   }
  }
  printf("%.4f\n",dp[0]);
 }
 return 0;
}

题意:有n个盒子,每个盒子里装有礼物,有m个人,然后每个人都会拿盒子,如果盒子里有礼物,就把礼物拿走,盒子依然放回去。求礼物个数的期望。

方程:dp[i]=1.0-dp[i+1]/n+dp[i+1];
SGU 495

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define mod 1000000007
typedef long long ll;
double dp[100005];
int main(){
 int n,m;
 while(scanf("%d%d",&n,&m)!=EOF){
  dp[m]=1.0;
  for(int i=m-1;i>=1;i--) 
   dp[i]=1.0-dp[i+1]/n+dp[i+1];
  printf("%.10f\n",dp[1]);
 }
 return 0;
}

逆向考虑,转自链接

#include <iostream>
#include <algorithm
#include <cstdio>
#include <cmath>
using namespace std;
int main()
{
    int n, m;
    while(~scanf("%d%d", &n, &m))
    {
        double p = (double)(n-1)/n;
        double ans = n - n*pow(p, m);
        printf("%.10lf\n", ans);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值