概率类题目小练

一般求概率的题目都是正着求,和求期望相反。但裸的求概率一般不多,很多都需要加以优化。最常见的有矩阵优化,记忆化搜索等,遇到有环的存在时需要用到高斯消元。

矩阵优化   POJ 3744

题目链接:http://poj.org/problem?id=3744

题意:在一条不满地雷的路上,你现在的起点在1处。在N个点处布有地雷,1<=N<=10。地雷点的坐标范围:[1,100000000].每次前进p的概率前进一步,1-p的概率前进两步。问顺利通过这条路的概率。
很裸的状态转移,并用矩阵乘法分段优化,里面也存在环,但由于转移方程里面每一项都和dp[0]也就是答案有关,可以直接手动推最终公式。

设dp[i]表示到达i点的概率,则初始值dp[1]=1.

很容易想到转移方程:dp[i]=p*dp[i-1]+(1-p)*dp[i-2];

但是由于坐标的范围很大,直接这样求是不行的,而且当中的某些点还存在地雷。

N个有地雷的点的坐标为 x[1],x[2],x[3]```````x[N].

我们把道路分成N段:

1~x[1],x[1]+1~x[2]、、、x[N-1]+1~x[N].

这样每一段只有一个地雷。我们只要求得通过每一段的概率。乘法原理相乘就是答案。

对于每一段,通过该段的概率等于1-踩到该段终点的地雷的概率。

就比如第一段 1~x[1].  通过该段其实就相当于是到达x[1]+1点。那么p[x[1]+1]=1-p[x[1]].

但是这个前提是p[1]=1,即起点的概率等于1.对于后面的段我们也是一样的假设,这样就乘起来就是答案了。

对于每一段的概率的求法可以通过矩阵乘法快速求出来。

 1 //#include<bits/stdc++.h>
 2 #include<stdio.h>
 3 #include<algorithm>
 4 using namespace std;
 5 const int maxn=2;
 6 struct node
 7 {
 8     double f[maxn][maxn];
 9 };
10 int num[15];
11 node solve(node a,node b)
12 {
13     node ans;
14     for(int i=0;i<maxn;i++)
15         for(int j=0;j<maxn;j++)
16     {
17         ans.f[i][j]=0.0;
18         for(int k=0;k<maxn;k++)
19             ans.f[i][j]+=a.f[i][k]*b.f[k][j];
20     }
21     return ans;
22 }
23 node power(node x,int y)
24 {
25     node ans={1,0,0,0};
26     while(y)
27     {
28         if(y&1)
29             ans=solve(ans,x);
30         x=solve(x,x);
31         y/=2;
32     }
33     return ans;
34 }
35 int main()
36 {
37     int n;
38     double p;
39     while(~scanf("%d%lf",&n,&p))
40     {
41         for(int i=1;i<=n;i++)
42             scanf("%d",&num[i]);
43         sort(num+1,num+1+n);
44         if(num[1]==1)
45         {
46             printf("0.0000000\n");
47             continue;
48         }
49         node x{p,1,1.0-p,0};
50         double ans=1.0;
51         for(int i=1;i<=n;i++)
52         {
53             if(num[i]==num[i-1]) continue;
54             node f=power(x,num[i]-num[i-1]-1);
55             ans*=1.0-f.f[0][0];
56         }
57         printf("%.7f\n",ans);
58     }
59     return 0;
60 }

记忆化搜索  CF 148D
题目链接:http://codeforces.com/problemset/problem/148/D

袋子里有w只白鼠和b只黑鼠
龙和公主轮流从袋子里抓老鼠。谁先抓到白色老师谁就赢。
公主每次抓一只老鼠,龙每次抓完一只老鼠之后会有一只老鼠跑出来。
每次抓老鼠和跑出来的老鼠都是随机的。
如果两个人都没有抓到白色老鼠则龙赢。公主先抓。
问公主赢的概率。

存在用dfs搜索和for循环查询的方法,但for循环推公式比较麻烦,建议使用dfs

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=1005;
 4 double dp[maxn][maxn];  //用dp记录每种状态公主获胜的概率
 5 int vis[maxn][maxn];
 6 double dfs(int x,int y)
 7 {
 8     if(x<=0) return 0;
 9     if(y<=0) return 1;
10     if(vis[x][y]) return dp[x][y];  //避免重复的求概率,不然会超时
11     vis[x][y]=1;
12     double ans=1.0*x/(x+y);  //公主直接摸到白球
13     if(y>=2)  //若黑球小于两个,但前面保证有黑球,所以黑球被公主摸走,龙摸到白球,赢的概率为0
14     {
15         double k=1.0*y/(x+y);  //公主摸一个黑球
16         y--;
17         k*=1.0*y/(x+y);  //龙摸一个黑球
18         y--;
19         dp[x-1][y]=dfs(x-1,y);  //白球少一个的情况
20         dp[x][y-1]=dfs(x,y-1);  //黑球少一个的情况
21         ans+=k*(1.0*x/(x+y)*dp[x-1][y]+1.0*y/(x+y)*dp[x][y-1]);
22     }
23     return ans;
24 }
25 int main()
26 {
27     int a,b;
28     scanf("%d%d",&a,&b);
29     printf("%.9f\n",dfs(a,b));
30     return 0;
31 }

二进制技巧  POJ 3071
题目链接:http://poj.org/problem?id=3071

2^n个队进行足球赛,每个队打败另外一个队都有一个概率。
问最后胜利的概率最大的是哪只球队。
注意:每个队只能和他旁边的队比赛,(1,2)(3,4)......

 1 #include<stdio.h>
 2 #include<algorithm>
 3 using namespace std;
 4 const int maxn=7;
 5 const int maxm=(1<<maxn)+5;
 6 double p[maxm][maxm],dp[maxn][maxm];  //dp[i][j]表示第i场比赛第j队获胜的概率
 7 int main()
 8 {
 9     int n;
10     while(scanf("%d",&n),n!=-1)
11     {
12         int m=(1<<n);
13         //注意给队伍的编号是0~m-1,接下来会省事一点
14         for(int i=0; i<m; i++)
15             for(int j=0; j<m; j++)
16                 scanf("%lf",&p[i][j]);
17         for(int i=0; i<m; i++)
18             dp[0][i]=1.0;  //初始化还没开始比赛时每只队伍出线的概率都为1
19         for(int i=1; i<=n; i++)
20             for(int j=0; j<m; j++)
21             {
22                 dp[i][j]=0;
23                 int f=j/(1<<(i-1));
24                 f^=1;
25                 for(int k=f*(1<<(i-1)); k<(f+1)*(1<<(i-1)); k++)
26                     dp[i][j]+=dp[i-1][k]*dp[i-1][j]*p[j][k];
27             }
28         int ans=0;
29         double sum=dp[n][0];
30         for(int i=1; i<m; i++)
31             if(dp[n][i]>sum)
32             {
33                 sum=dp[n][i];
34                 ans=i;
35             }
36         printf("%d\n",ans+1);
37     }
38     return 0;
39 }
时间: 2024-10-22 18:01:03

概率类题目小练的相关文章

概率和期望类题目综合分析

先给出学习资料吧:kuangbin的博客:  https://www.cnblogs.com/kuangbin/archive/2012/10/02/2710606.html kuangbin的博客里面有3篇论文,讲的非常好,但是有点难(非常难),推荐全部打印下来 首先概率和期望类题目有哪几种做法呢? 用鬲融的总结的话有以下几种:直接计算(这样只要考验你的公式推理,一点代码都不需要)  动态规划的方法(也就是传说中的概率正着算,期望反着求)迭代的方法(其实我分不太清这样和动态规划的区别) 概率-

模拟人机交互类题目

人机交互,顾名思义,就是人与计算机间的交流互动,我们对计算机的每一次操作程序中的每一条语句都是与计算机的交流,这类题目是将人和计算机调换位置,例如猜数游戏,常规的做法是让人输入数,计算机判断大还是小,而这类人机交互题目中需要你的程序充当人来输入数据,再自己来判断大小. 例题1:猜数游戏http://codeforces.com/gym/101021 分析:范围[1,1e6],二分判断.程序输出数字,我们输入大小.(这个代码是随机数). 1 #include<bits/stdc++.h> 2 u

博弈论类题目小结——转载

出处http://blog.csdn.net/ACM_cxlove?viewmode=contents    by---cxlove 首先当然要献上一些非常好的学习资料: 基础博弈的小结:http://blog.csdn.net/acm_cxlove/article/details/7854530 经典翻硬币游戏小结:http://blog.csdn.net/acm_cxlove/article/details/7854534 经典的删边游戏小结:http://blog.csdn.net/acm

算法小练#1 - Dany Yang

开始记录每周做过的算法题,这是第一周,新的开始 1021. 删除最外层的括号 题目要求如下: 有效括号字符串为空 ("")."(" + A + ")" 或 A + B,其中 A 和 B 都是有效的括号字符串,+ 代表字符串的连接.例如,"","()","(())()" 和 "(()(()))" 都是有效的括号字符串. 如果有效字符串 S 非空,且不存在将其拆分为 S

3.12课程小练以及vim编辑器的基本用法(部分)

 课程小练 1. 通过man帮助手册,自行总结which.whereis.whatis命令的使用方法: which:展示出shell命令的完整路径: 格式: which [options] [--] programname [...] whereis:基于二进制的,有源的,和文件或命令的记录手册 格式:whereis [options] name... whatis:在 whatis 数据库里查找完整的单词 格式:whatis - 2. du命令: du - 报告磁盘空间使用情况 du -a,

关于理解python类的小题

今天看了python部落翻译的一篇<一道python类的小题>文章,感觉挺有启发性,记录下来: 1 print('A') 2 class Person(object): 3 print('B') 4 def __int__(self,name): 5 print('C') 6 self.name = name 7 print('D') 8 print('E') 9 10 11 p1= Person('name1') 12 p2 = Person('name2') 输出结果: A B D E C

C# 类使用小demo

太晚了,不说了,直接上图 运行结果 C# 类使用小demo

python自测——操作类题目

操作类题目 49.Python 交换两个变量的值50.在读文件操作的时候会使用 read.readline 或者 readlines,简述它们各自的作用51.json 序列化时,可以处理的数据类型有哪些?如何定制支持 datetime 类型?52.json 序列化时,默认遇到中文会转换成 unicode,如果想要保留中文怎么办?53.有两个磁盘文件 A 和 B,各存放一行字母,要求把这两个文件中的信息合并(按字母顺序排列),输出到一个新文件 C 中.54.如果当前的日期为 20190530,要求

动态规划小练

终于意识到动规的水平差得一批了.这边开个小专题练一下. 题目列表是学长 frank_c1 的博客.这样一来可以保证质量,二来也有自己能看懂的题解. 事实上很多题意也是贺的 这里还是挂个链接吧:orz (刷新以获取数学公式) [APIO 2014] Beads and wires 题意 在达芬奇时代,有一个流行的儿童游戏称为连珠线.当然,这个游戏是关于珠子和线的.线是红色或蓝色的,珠子被编号为 $ 1 $ 到 $ n $ .这个游戏从一个珠子开始,每次会用如下方式添加一个新的珠子: $ Appen