概率DP入门题

概率问题的论文

1.算法合集之《信息学竞赛中概率问题求解初探》

2.有关概率和期望问题的研究

3.算法合集之《浅析竞赛中一类数学期望问题的解决方法》

二 入门题目

1、POJ 3744 Scout YYF I (简单题)

题意:一条路上有n个地雷 ,a[i]代表第i个地雷放的位置,求安全走过这段路的概率

分析:若第k个位置有地雷则安全走过这个位置的方案为在第k-1个位置跳两步概率为(1-p)

从反面考虑 已经安全走过了第i-1个雷 则在第i个雷的死掉的概率为 1-p(从走到a[i-1]走到a[i])  P=p*ans[i-1]+(1-p)*ans[i-2]

ans[i]代表走到i位置的概率,由于n比较大 需要用矩阵进行优化

解题报告:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

int a[20];

struct matrix
{
    double m[2][2];
};

matrix I={1.0,0,0,1.0};

matrix multi(matrix A,matrix B)
{
    matrix C;
    for(int i=0;i<2;i++){
        for(int j=0;j<2;j++){
            C.m[i][j]=0;
            for(int k=0;k<2;k++)
                C.m[i][j]+=A.m[i][k]*B.m[k][j];
        }
    }
    return C;
}
double pow(int k,matrix A)
{
    matrix ans = I,p=A;
    while(k){
        if(k&1){
            ans=multi(ans,p);
            k--;
        }
        k>>=1;
        p=multi(p,p);
    }
    return ans.m[0][0];
}

int main()
{
    int n;
    double p;
    while(cin>>n>>p){
        for(int i=1;i<=n;i++)
            cin>>a[i];
        a[0]=0;
        sort(a,a+n+1);
        matrix A={p,1.0-p,1.0,0};
        double ans=1;
        for(int i=0;i<n;i++){
            ans*=(1-pow(a[i+1]-a[i]-1,A));
        }
        printf("%.7lf\n",ans);
    }
    return 0;
}

2、POJ 3071 Football      (简单题)

足球赛的淘汰赛问题。问最后胜利的概率最大的球队。每个队的胜率都用dp算一下比较

解题报告

3、codeforces 148D Bag of mice   (简单题)

抓老鼠问题。记忆化搜索的话不是很难,要写成for循环的那就比较麻烦了

解题报告

4、POJ 2151 Check the difficulty of problems   (简单题)

算很常见的一种dp表示吧。 学会 “至少” 这类问题角度的转化。

解题报告

5、ZOJ  3380 Patchouli‘s Spell Cards (中等题)

有m个位置,每个位置填入1~n中的一个数,求至少有L个数一样的概率。 dp转移还行,就是要用Java的     高精度                   解题报告

6、SGU  495 Kids and Prizes     (YY题)

YY题,O(1)推出结论,想不到就觉得比较难, 分析问题的角度值得学习。

解题报告

7、POJ 2096 Collecting Bugs   (简单题)

题意:一个人一天只能找出一个bug来 一个公司有s个子公司 ,有n种bug,让这个人去找,求找出所有的n种bug而且每个公司都要找出bug所需要的时间的期望

分析:dp求期望入门题。关键要体会为什么要倒着推过来

dp[i][j]表示在i个公司中一共找到了j种bug

注:E(aA+bB+cC+.....n*N)=a*E(A)+b*E(B)+.......+n*E(N);

状态转移方程很好理解

dp[i][j]=(dp[i+1][j]*p1+dp[i][j+1]*p2+dp[i+1][j+1]+1)/(1-p4);

p1=(s-i)*j/n/s;

p2=i*(n-j)/n/s;

p3=(s-i)*(n-j)/n/s;

p4=i*j/n/s;

解题报告

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;

const int maxn = 1010;

double dp[maxn][maxn];

int main()
{
    int n,s;
    while(~scanf("%d%d",&n,&s)){
        dp[s][n]=0;
        for(int i=s;i>=0;i--){
            for(int j=n;j>=0;j--){
                if(i==s&&j==n)
                continue;
                dp[i][j]=(dp[i+1][j]*(s-i)*j*1.0/(s*n*1.0)+dp[i+1][j+1]*(s-i)*(n-j)*1.0/(s*n*1.0)+dp[i][j+1]*i*(n-j)*1.0/(s*n*1.0)+1.0)/(1.0-i*j*1.0/n/s);
            }
        }
        printf("%.4lf\n",dp[0][0]);
    }
    return 0;
}

8、HDU 3853 LOOPS      (简单题)

同第6题, 但要注意一个小问题

题意:一个r*c的地图 一个人在(1,1)每次可以留在原地 或者消耗两个体力向左走一格或则向下走一格,求走到(r,c)所消耗的体力的期望

分析:dp[i][j]表示从(i,j)走到终点所消耗体力的期望

dp[i][j]=(dp[i+1][j]*p1+dp[i][j+1]*p2+2)/(1-p3)

p1为向右走的概率 ,p2为向下走的概率 ,p3为原地不动的概率

注:E(aA+bB+cC+.....n*N)=a*E(A)+b*E(B)+.......+n*E(N); 包含状态A,B,C的期望可以分解子期望求解

解题报告

#include <iostream>
#include <cmath>
#include <cstdio>
#include <cstring>
using namespace std;

const int maxn = 1002;

double map[maxn][maxn][3];
double dp[maxn][maxn];

int main()
{
    int r,c;
    while(~scanf("%d%d",&r,&c)){
        for(int i=1;i<=r;i++)
            for(int j=1;j<=c;j++)
            scanf("%lf%lf%lf",&map[i][j][0],&map[i][j][1],&map[i][j][2]);
        memset(dp,0,sizeof(dp));
        for(int i=r;i>=1;i--){
            for(int j=c;j>=1;j--){
                if(i==r&&j==c)
                    continue;
                if(map[i][j][0]==1.00)
                    continue;
                dp[i][j]=(map[i][j][1]*dp[i][j+1]+map[i][j][2]*dp[i+1][j]+2)/(1-map[i][j][0]);
            }
        }
        printf("%.3lf\n",dp[1][1]);
    }
    return 0;
}

9、HDU  4405 Aeroplane chess   (简单题)

这题是2012年网络赛的题目。同第6题,只是题目多加了一个小小的条件

分析:dp[i]=1/6(dp[i+1]+....+dp[i+6]+1)   如果i可以直接到k的话 则dp[i]=dp[k]; dp[i]表示从i到终点所要扔的色子次数的期望

解题报告

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;

const int maxn = 100007;

double dp[maxn];

int f[1010][2];

int main()
{
    int n,m;
    while(~scanf("%d%d",&n,&m)){
        if(n==0&&m==0)
        break;
        for(int i=0;i<m;i++)
            scanf("%d%d",&f[i][0],&f[i][1]);
        memset(dp,0,sizeof(dp));
        double p = 1.0/6;
        for(int i=n;i>=0;i--){
            if(i>=n) continue;
            dp[i]=(dp[i+1]+dp[i+2]+dp[i+3]+dp[i+4]+dp[i+5]+dp[i+6])*p+1;
            for(int j=0;j<m;j++){
                if(i==f[j][0]){
                    dp[i]=dp[f[j][1]];
                    break;
                }
            }
        }
        printf("%.4lf\n",dp[0]);
    }
    return 0;
}

10、ZOJ 3640  Help Me Escape    (简单题)

做完6,7,8题后仔细想想,还是差不多的题, 记忆化搜索也容易想到

解题报告

#include<cstdio>
#include<cstring>
#include<cmath>
#define max(a,b) a>b?a:b
const int LMT=20003;
const double is=0.5*(1+sqrt(5));
double dp[LMT];
int have[102];
int main()
{
    int i,n,f,j,all;
    while(~scanf("%d%d",&n,&f))
    {
        memset(dp,0,sizeof(dp));
        all=-1;
        for(i=0;i<n;i++)
        {
            scanf("%d",&have[i]);
            all=max(all,have[i]);
        }
        all<<=1;
        for(i=max(all,f);i>=f;i--)
        {
            for(j=0;j<n;j++)
                if(i>have[j])dp[i]+=(int)(is*have[j]*have[j]);
                else dp[i]+=1+dp[i+have[j]];
                    dp[i]/=n;
        }
        printf("%.3lf\n",dp[f]);
    }
    return 0;
}

11、ZOJ 3822 Domination (简单题)

题意:给定一个r*c的棋盘 每一步可以放一个棋子 求多少步可以使每行每列都有棋子的期望

分析:这题是2014年 2014 ACM-ICPC Asia Mudanjiang Regional 的题目,其实只要做过 概率dp的题目就很好写的

dp[i][j][k]表示一共用了i个棋子 使i行k列有了棋子

dp[i][j][k]=(dp[i+1][j][k]*p1+dp[i+1][j+1][k]*p2+dp[i+1][j][k+1]*p3+dp[i+1][j+1][k+1]*p4)

p1=(j*k-i)/(r*c-i);

p2= (r-j)*k/(r*c-i);

p3=(c-k)*j/(r*c-i);

p4=(r-j)*(c-k)*(r*c-i);

解题报告:

#include <iostream>
#include <cstring>
#include <cstdio>

using namespace std;

const int maxn = 51;

double dp[maxn*maxn][maxn][maxn];

int main()
{
    int r,c,t;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&r,&c);
        memset(dp,0,sizeof(dp));
        for(int i=r*c-1;i>=0;i--){
            for(int j=r;j>=0;j--){
                for(int k=c;k>=0;k--){
                    if(j==r&&k==c) continue;//判断分母是不是为0
                    if(j*k<i) continue;//判断分子是不是负数
                    double p1=1.0*(j*k-i)/(r*c-i);
                    double p2=1.0*(r-j)*k/(r*c-i);
                    double p3=1.0*(c-k)*j/(r*c-i);
                    double p4=1.0*(r-j)*(c-k)/(r*c-i);
                    //  cout<<"p1 "<<p1<<endl;
                    // cout<<"p2 "<<p2<<endl;
                    //cout<<"p3 "<<p3<<endl;
                    //cout<<"p4 "<<p4<<endl;
                    dp[i][j][k] =dp[i+1][j][k]*p1+dp[i+1][j+1][k]*p2+dp[i+1][j][k+1]*p3+dp[i+1][j+1][k+1]*p4+1.0;
                }
            }
        }

        printf("%.8lf\n",dp[0][0][0]);
    }
return 0;
}

12、HDU 4336 Card Collector  (简单题)

状态压缩概率DP。或者用容斥原理直接求。

题意:有n种卡片,每买一包零食则可能得到其中的一种也可能得不到,得到第i种卡片的概率为pi求,收集齐所有的卡片需要的买零食的期望

由于n比较小我们可以进行状态压缩

dp[i] 化成二进制1的位置代表收集了 这几种所需要买的零食的期望

eg: dp[(1101)2] =(dp[(1100)2]*p1+dp[(1001)2]*p3+dp[(0101)2]*p4+1)/(1-p3-p(零食里没有卡片))

解题报告

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;

const int maxn = 1<<20;

double dp[maxn+1];
double p[25];

int main()
{
    int n;
    while(~scanf("%d",&n)){
        p[0]=1;
        for(int i=1;i<=n;i++){
            scanf("%lf",p+i);
            p[0]-=p[i];
        }
        dp[0]=0;
        double x;
        for(int i=1;i<(1<<n);i++){
            x=p[0];
            dp[i]=1;
            for(int j=0;j<n;j++){
                if((1<<j)&i) dp[i]+=p[j+1]*(dp[i-(1<<j)]);
                else x+=p[j+1];
            }
            dp[i]/=(1-x);
        }
        printf("%.4lf\n",dp[(1<<n)-1]);
    }
    return 0;
}

13、ZOJ 3329  One Person Game   (中等题-)

骰子求期望的题, 递推公式有点麻烦。

解题报告

14、hdu 4652 Dice     (中等题-)

dp求期望 推数学公式, 最近第5场多校题, 赛后发现其实是道很基础的题,可惜没学过, 用高中知识就能推出来了

解题报告

15、HDU 4035 Maze     (中等题+)

树上的dp递推, 写出递推关系方程组后,用dfs从树的叶子节点一路往上迭代方程求解

解题报告

16、HDU 4089 Activation    (中等题)

2011年北京现场赛的题目, 用求期望的方法 求概率的题,公式有一点点繁琐,仔细想也是可以做出来的                     、

解题报告

17、HDU 4418 Time travel  (中等题)

高斯消元,这题是学长出的,目的是坑人题意的, 题意理解以后就是很裸的高斯消元(用程序解方程),但还是有很多坑

只做了一部分题目,剩下的以后做了会继续更新。。。

时间: 2024-10-23 14:14:27

概率DP入门题的相关文章

hdu 5001 walk 概率dp入门题

Description I used to think I could be anything, but now I know that I couldn't do anything. So I started traveling. The nation looks like a connected bidirectional graph, and I am randomly walking on it. It means when I am at node i, I will travel t

hdu 4405 Aeroplane chess 概率dp入门题

Description Hzz loves aeroplane chess very much. The chess map contains N+1 grids labeled from 0 to N. Hzz starts at grid 0. For each step he throws a dice(a dice have six faces with equal probability to face up and the numbers on the faces are 1,2,3

13年山东省赛 The number of steps(概率dp水题)

转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud The number of steps Time Limit: 1 Sec  Memory Limit: 128 M Description Mary stands in a strange maze, the maze looks like a triangle(the first layer have one room,the second layer have two ro

hdu4405概率dp入门

Aeroplane chess Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1122    Accepted Submission(s): 762 Problem Description Hzz loves aeroplane chess very much. The chess map contains N+1 grids lab

数位DP入门题 hdu 2089 hdu 3555

hdu 2089 不要62 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2089 题意:对于每次给出的一个区间,找出区间内多少个数字没有出现62和4. 思路: 数位DP入门题,对于dfs设置3个参数. 一个表示现在进行到第几位, 一个表示前一个标记状态,这里表示上一位是不是6. 一个表示是否现在是这位可以取到的最大的数字. 如果上一位是6,那么这位不可以取2.且当前位都不可以取4. 1 #include <bits/stdc++.h> 2 us

Hdu-1565 方格取数(1) (状态压缩dp入门题

方格取数(1) Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4702    Accepted Submission(s): 1782 Problem Description 给你一个n*n的格子的棋盘,每个格子里面有一个非负数. 从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能相邻,并且取出

hdu3853之概率dp入门

LOOPS Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 125536/65536 K (Java/Others) Total Submission(s): 1651    Accepted Submission(s): 653 Problem Description Akemi Homura is a Mahou Shoujo (Puella Magi/Magical Girl). Homura wants to help h

poj2096之概率DP入门

Collecting Bugs Time Limit: 10000MS   Memory Limit: 64000K Total Submissions: 2041   Accepted: 974 Case Time Limit: 2000MS   Special Judge Description Ivan is fond of collecting. Unlike other people who collect post stamps, coins or other material st

poj 3254 状压dp入门题

1.poj 3254  Corn Fields    状态压缩dp入门题 2.总结:二进制实在巧妙,以前从来没想过可以这样用. 题意:n行m列,1表示肥沃,0表示贫瘠,把牛放在肥沃处,要求所有牛不能相邻,求有多少种放法. #include<iostream> #include<cstring> #include<cmath> #include<queue> #include<algorithm> #include<cstdio> #d