2020寒假培训期望dp(概率dp)题解

如何提高博客访问量?

概率期望dp一般都是逆推。正推的话要计算期望的期望,非常麻烦!一般来说,总有一个末状态是一定会发生,从这个状态开始逆推可以简化许多问题。
期望dp和普通的dp的不同处。普通的dp可能纪录的是dp[i]到了i这个状态时的最优解,而期望dp一般纪录dp[i]以i这个状态为起点能得到的最优解。


E.Discovering Gold
题意:大富翁地图。丢筛子,每个格子有val,如果最后丢出筛子超出终点就重新丢,求最后获得的val期望。
解题思路:不难发现,最后会一定停在终点。所以建立dp[终点]=1*val[终点],向前推。dp储存从这个点开始能获得的总价值的期望

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
using namespace std;
#define ll long long
#define MT(a,b) memset(a,b,sizeof(a))
const int mod=10007;
const int maxn=1E5+5;
const int ONF=-0x3f3f3f3f;
const int INF=0x3f3f3f3f;
int num[105];
double dp[105];

int main (){
    int t,n;
    scanf ("%d",&t);
    for (int turn=1;turn<=t;turn++){
        scanf ("%d",&n);
        for (int i=1;i<=n;i++){
            scanf ("%d",&num[i]);
            dp[i]=num[i];
        }
        int qwe=1;
        for (int i=n-1;i>=1;i--){
            if (qwe>6) qwe=6;
            for (int j=1;j<=qwe;j++){
                dp[i]+=(double)(dp[i+j]/qwe);
            }
            qwe++;
        }
        printf("Case %d: %lf\n",turn,dp[1]);
    }
    return 0;
}

F - Aeroplane chess
题意:大富翁地图。丢筛子,两个格子间可能可以直接到达(不耗费时间)。只要最后超出终点就算到达。求到达的期望丢筛子次数。
解题思路:水题

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
using namespace std;
#define ll long long
#define MT(a,b) memset(a,b,sizeof(a))
const int mod=10007;
const int maxn=2e5+5;
const int ONF=-0x3f3f3f3f;
const int INF=0x3f3f3f3f;
double dp[maxn];
int qwe[maxn];
int main (){
    int n,m,a,b;
    while (~scanf ("%d%d",&n,&m)){
        if (n==0&&m==0) break;
        MT(dp,0);
        MT(qwe,0);
        for (int i=1;i<=m;i++){
            scanf("%d%d",&a,&b);
            qwe[a]=b;
        }
        for (int i=n-1;i>=0;i--){
            if (qwe[i]!=0){
                dp[i]=dp[qwe[i]];
            } else{
                double tmp=0;
                for (int j=i+1;j<=i+6;j++){
                    tmp+=dp[j];
                }
                dp[i]+=tmp/6;dp[i]+=1;
            }
        }
        printf("%.4f\n",dp[0]);
    }
    return 0;
}


G - Bag of mice
题意:有一个袋子,袋子里面有w只白鼠,b只黑鼠。公主和龙轮流从袋子里抓老鼠,公主先抓。龙抓完老鼠后,随机跳出一只老鼠(不算龙抓的)。谁先抓到白鼠谁赢。求公主赢的概率。
解题思路:https://blog.csdn.net/weixin_44003265/article/details/103864741不想过去的人看图也行。
在这里插入图片描述
错误原因:我第一次看到这个题的时候,想正向推。每一次求抓白鼠的期望概率。显然,从第2次开始,就需要不停地使用前面的期望去修正这次的期望。正推是求不出来的(至少我是 ^ _ ^);

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
using namespace std;
#define ll long long
#define MT(a,b) memset(a,b,sizeof(a))
const int mod=10007;
const int maxn=1e3+5;
const int ONF=-0x3f3f3f3f;
const int INF=0x3f3f3f3f;
double dp[maxn][maxn];
int main (){
    int w,b;
    scanf ("%d%d",&w,&b);
    MT(dp,0);
    for (int i=1;i<=w;i++) dp[i][0]=1;
    for (int i=1;i<=w;i++){
        for (int j=1;j<=b;j++){
            dp[i][j]=i*1.0/(i+j);
            if (j>=2) dp[i][j]+=(j*1.0/(i+j)*(j-1)*1.0/(i+j-1)*i*1.0/(i+j-2))*dp[i-1][j-2];
            if (j>=3) dp[i][j]+=(j*1.0/(i+j)*(j-1)*1.0/(i+j-1)*(j-2)*1.0/(i+j-2))*dp[i][j-3];
        }
    }
    printf("%.9f\n",dp[w][b]);
    return 0;
}

发布了33 篇原创文章 · 获赞 15 · 访问量 838

猜你喜欢

转载自blog.csdn.net/weixin_43925900/article/details/103937702
今日推荐