动态规划在概率论中的应用:产生N种不同结果的概率之间的联系

来源:互联网 发布:销售开单软件 编辑:程序博客网 时间:2024/06/07 16:27
动态规划的应用十分常见,今天介绍一种在概率论中求期望时所用的动态规划方法。
因为在求期望时,我们需要知道N种结果中,每种结果的概率p[i]和每种结果值k[i],那么最终的期望值即为E=p[1]k[1]+p[2]k[2]+...p[N]k[N]。某种题意要求下,各个p[i]的值之间有关系,p[i]=f(p[i+1]),这种情况下,我们便可以用动态规划来解决。
背景:
这次招聘会一共有N个人,我们公司给大家准备了一些礼物,但是我们并不知道这些人具体喜欢什么,现在库房共有m种礼物,每种礼物有Ci件,共N件。而我们大致知道每个人选择某种礼物的概率,即能知道Pij(编号为i的人选择第j种礼物的概率)。现在所有人按编号依次领礼物(第1个人先领,第N个人最后领),领礼物时,参加者会按照预先统计的概率告诉准备者自己想要哪一种礼物,如果该种礼物在他之前已经发放完了则他会领不到礼物,请帮我们计算出能能领到礼物的期望人数。

输入描述:
第一行包含两个整数N(1≤N≤300),M(1≤M≤100),用单个空格隔开。表示公有N个应聘者,M种礼物。第二行为M个整数,依次为Ci,第i种礼物的个数。接下来的N行,每行M个实数,一次为Pij,第i个人选择第j种礼物的概率。


输出描述:
一行输出期望人数。结果保留1位小数。

输入例子:
2 21 10.3 0.70.7 0.3

输出例子:
1.6(样例解释:共有4种选择(1,1),(1,2),(2,1),(2,2),概率分别为0.21、0.09、0.49、0.21,(1,1),(2,2)这两种选择只有1个人能拿到礼物,(1,2),(2,1)这两种选择有2个人能拿到礼物,所以期望为1*(0.21+0.21) + 2*(0.09+0.49) = 1.58,保留一位小数为1.6。)
解题思路:
/*解题思路:
(领到礼物的人数)=(被领的礼物数)=(礼品总数)-(剩下的礼物数)
问题可以转化为求(剩下的礼物数),考虑某种礼物:
假设有3件,剩n件的概率为P_n,则派发礼物之前,P_3=1,P_2=P_1=P_0=0
假设第一个人选择这件礼物的概率是0.2,则经过他选择后,P_3=0.8,P_2=0.2,P_1=P_0=0
如此类推,经过第i个人选择后(选择概率为p),剩下k件的概率是:
P_k'=P_k*(1-p)+P_(k+1)*p (原本有k件的概率*不选择这礼物的概率 + 原本有k+1件的概率*选择这礼物的概率)
经过N个人选择后,就能得出剩下的期望数量就等于P_3*3+P_2*2+P_1*1
代码为了易懂,所以写得冗长一点,希望大家能读懂
*/
#include <iostream>#include <vector>#include <iomanip>using namespace std;int main(){    int n,m;    while(cin>>n>>m){        vector<int> c(m);        for (int i = 0; i < m; ++i)        {            cin>>c[i];        }        vector<vector<double>> p(n,vector<double>(m));        for (int i = 0; i < n; ++i)        {            for (int j = 0; j < m; ++j)            {                cin>>p[i][j];            }        }        vector<vector<double>> dp(m);//dp[i][j]是第i种礼物剩下j的概率,也是第i种礼物被取走c[i]-j的概率        for (int i = 0; i < m; ++i)        {            dp[i]=vector<double>(c[i]+1,0.0);            dp[i][c[i]]=1.0;        }        for (int k = 0; k < n; ++k)//k个人依次取        {            for (int i = 0; i < m; ++i)            {                if(c[i]!=0){//这里是自少向多更新,想想为什么,因为要获得还剩j个的概率时,需要知道还剩j+1个的概率.                    //类似于后移拷贝,防止从多向少更新时,发生数据覆盖。                    dp[i][0]=dp[i][0]+dp[i][1]*p[k][i];                    for (int j = 1; j < c[i]; ++j)                    {                        dp[i][j]=dp[i][j]*(1-p[k][i])+dp[i][j+1]*p[k][i];                    }                    dp[i][c[i]]*=1-p[k][i];                }            }        }        double E=0.0;//求期望。        for (int i = 0; i < m; ++i)        {            for (int j = 0; j <= c[i]; ++j)            {                E+=dp[i][j]*(c[i]-j);            }        }        cout<<setiosflags(ios::fixed)<<setprecision(1)<<E<<endl;    }    return 0;}



0 0
原创粉丝点击