石头剪刀步(rps):dp,概率&期望

既然已经给std了,直接扔代码啦。代码注释还是不错哒。

因为我也有点懵,不明白的或有不同见解的一定要在评论区喷我啊!

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 //首先题意可能还有人理解错了。题目的意思是你要根据对手分别出了几个石头几个剪刀来决策
 4 //而并不是一场战斗结束后你就能知道对方具体是谁从而直接推断剩下的人
 5 #define g f[i][j][k]//压行,和那个题解里的含义不一样,但没有影响
 6 #define d(x,k) for(int x=k;x>=0;--x)//压行,字少
 7 int n;double x[51][4],f[51][51][51][4],ans,c[51][51];
 8 //f数组的含义:当最后一维为1~3时表示第i+j+k+1个人在前面的人出了i个1,j个2,k个3的情况下出1~3的概率
 9 //当最后一维为0时表示前i+j+k个人出了i个1,j个2,k个3的概率,即那个题解里的g数组
10 int main(){
11     scanf("%d",&n); f[0][0][0][0]=1;//初始化
12     for(int i=1;i<=n;++i) scanf("%lf%lf%lf",&x[i][1],&x[i][3],&x[i][2]),
13         x[i][1]/=300,x[i][2]/=300,x[i][3]/=300;
14     //读入概率,注意顺序是132。把石头剪刀步分别抽象为123,故1胜2,2胜3,3胜1
15     for(int i=0;i<=50;++i) c[i][0]=1;
16     for(int i=1;i<=50;++i) for(int j=1;j<=i;++j) c[i][j]+=c[i-1][j-1]+c[i-1][j];
17     //杨辉三角。注意:要用到50!级别的而没有取模,所以要开long long或double
18     for(int s=1;s<=n;++s) d(i,s) d(j,s-i) d(k,s-i-j) d(u,(i+j+k==s?0:3)){//有点像个背包
19         //你可以把s单独再开一维的数组来表示目前考虑到第几个人,更好理解但貌似会炸内存
20         //u为1~3时,分别枚举第几个人,前面的人出过几个1,2,3,这个人要出u
21         //注意u的枚举是当i+j+k!=s时才更新对方下一次出123的概率,否则只更新到达某状态的概率
22         //u为0时,计算到达这个状态的总概率(即题解中的g数组)
23         if(i)g[u]+=f[i-1][j][k][u]*x[s][1];//这个人s出了1,累加概率
24         //当u=0时,f[i][j][k][0]由f[i-1][j][k][0]转移而来(u=0并不考虑下一个人会出什么)
25         //在原状态出一个1即为新状态,后者的概率为x[s][1]。计算g数组就不必考虑其他f值的影响
26         //因为根据含义就有f[i][j][k][0]=f[i][j][k][1]+f[i][j][k][2]+f[i][j][k][3]
27         //当u>0时就不太一样了,计算的是接下来出1的概率
28         //它由上一轮对方出1的概率乘对方真的出了1的概率累加而来,此时i+j+k!=s
29         //因为你把这玩意当成一个背包不断往里面放对手来更新其概率
30         //意思大概就是“目前的状态已经是那样了而且下一轮你遇到了s”,然后s对你的概率产生的贡献
31         //所以就是你走到原状态的概率,乘上s出1的概率,就是s对目前状态的概率贡献
32         //所以i+j+k==s时不能枚举到3,因为相当于你的原状态里面已经有s个人了,可是你现在刚刚开始考虑第s个人啊
33         if(j)g[u]+=f[i][j-1][k][u]*x[s][2];//出2,同上
34         if(k)g[u]+=f[i][j][k-1][u]*x[s][3];//出3,同
35         if(u)g[u]+=f[i][j][k][1-1]*x[s][u];//不要管这个1-1,它只是为了在等宽字体下的整齐
36         //这个就是弥补了上面的缺陷。本层转移。不管目前的状态是什么,反正第s个人就是出u了
37         //与上面的并不重复。一个是在说s对以前的状态的贡献,这个是在说s对当前状态的贡献
38     }
39     d(i,n-1) d(j,n-1-i) d(k,n-i-j-1)//i+j+k不要枚举到n,因为已经进行过n轮后下一次再出什么已经不重要不记分了
40         ans+=max(max(g[1]+3*g[2],g[2]+3*g[3]),g[3]+3*g[1])/c[n][i+j+k]/(n-i-j-k);
41     //在每一种状态下(即确定对手已经出了i个1,j个2,k个3)时你都有唯一确定的最优决策来进行下一轮
42     //每一次决策时都会累加分数,3种决策分别对应出1,2,3.g[1]即为与1打平,3*g[2]即为战胜2
43     //你所说的最优决策就是根据已有信息(每个对手出了什么),通过猜测对手下一步会出什么来权衡3中决策
44     //至于为什么用到了组合数:因为你所算的概率只是到达这一步的概率,但是你是从n个人里随便选出了c[n][i+j+k]个人
45     //然而其实在同一场游戏中对于同样的i+j+k你只会选1次,在计算的时候你把概率累加在一起了,现在要求一个平均值
46     //再除一个(n-i-j-k)的原因也差不多,因为你是要从剩下的(n-i-j-k)个人里选出一个去挑战
47     //这一步的概率是1/(n-i-j-k),然而你在上面5层循环的时候并没有考虑,所以在这里统一除去
48     printf("%.12lf\n",ans);//给的std里是用%.12f输出double的,真是惊奇
49 }//把注释全删掉你就会发现这个代码只有21行811B

原文地址:https://www.cnblogs.com/hzoi-DeepinC/p/11331121.html

时间: 2024-10-10 12:41:15

石头剪刀步(rps):dp,概率&期望的相关文章

hdu-5816 Hearthstone(状压dp+概率期望)

题目链接: Hearthstone Time Limit: 2000/1000 MS (Java/Others)     Memory Limit: 65536/65536 K (Java/Others) Problem Description Hearthstone is an online collectible card game from Blizzard Entertainment. Strategies and luck are the most important factors

HDU3853-LOOPS(概率DP求期望)

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

HDU4405-Aeroplane chess(概率DP求期望)

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

HDU 4050 wolf5x (概率DP 求期望)

题意:有N个格子,1~N,起点在0,每个格子有一个状态(0,1,2,3),每次可以跨[a,b]步, 问走完N个格子需要步数的期望,每次尽量走小的步数,即尽量走a步,不能则走a+1,-- 状态0意味着你不能踏进对应的网格. 状态1意味着你可以??步入网格用你的左腿. 状态2意味着你可以??步入网格用你的右腿. 状态3意味着你可以进入网格用任何你的腿,而接下来的步骤中,您可以使用任何的腿;即你不需要遵循上述规则. 思路:借鉴了各路大神的思想理解了下. dp[i][j] :表示走到第 i 个格子在 j

HDU 4405 Aeroplane chess (概率DP求期望)

题意:有一个n个点的飞行棋,问从0点掷骰子(1~6)走到n点需要步数的期望 其中有m个跳跃a,b表示走到a点可以直接跳到b点. dp[ i ]表示从i点走到n点的期望,在正常情况下i点可以到走到i+1,i+2,i+3,i+4,i+5,i+6 点且每个点的概率都为1/6 所以dp[i]=(dp[i+1]+dp[i+2]+dp[i+3]+dp[i+4]+dp[i+5]+dp[i+6])/6  + 1(步数加一). 而对于有跳跃的点直接为dp[a]=dp[b]; #include<stdio.h>

HDU4336-Card Collector(概率DP求期望)

Card Collector Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2195    Accepted Submission(s): 1034 Special Judge Problem Description In your childhood, do you crazy for collecting the beautifu

SGU495 Kids and Prizes 概率DP,期望公式

题目 这题目首先进去以后,没地方提交,第一次做SGU的题目,只能在HUSTOJ上提交了 有n个盒子,里面有礼物的,m个人,每个人拿,拿过以后 把礼物取出来 把盒子放回去,求选中礼物数的期望 其实一开始就假设方程 dp[i]为 第i个人获得礼物的概率,但是状态转移方程不知道该怎么办,想了很久都没有办法, 其实首先边界为dp[1] = 1 第一个上来选的人肯定必中 接下来一个人的 则由两部分组成,dp[i] = (1 - dp[i - 1]) * dp[i - 1] + .........,因为上一

【BZOJ-1419】Red is good 概率期望DP

1419: Red is good Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 660  Solved: 257[Submit][Status][Discuss] Description 桌面上有R张红牌和B张黑牌,随机打乱顺序后放在桌面上,开始一张一张地翻牌,翻到红牌得到1美元,黑牌则付出1美元.可以随时停止翻牌,在最优策略下平均能得到多少钱. Input 一行输入两个数R,B,其值在0到5000之间 Output 在最优策略下平均能得到多少钱

【POJ 2096】Collecting Bugs 概率期望dp

题意 有s个系统,n种bug,小明每天找出一个bug,可能是任意一个系统的,可能是任意一种bug,即是某一系统的bug概率是1/s,是某一种bug概率是1/n. 求他找到s个系统的bug,n种bug,需要的天数的期望. 分析 计算期望E=∑所有可能需要的天数*概率 找到s个系统n种bug,需要最少max(s,n)天,而可能的天数是无穷的,这样计算很复杂,复杂到算不了. 所以考虑dp,期望E=∑(昨天可以转移到现在状态的所有可能的情况的期望+1)*概率=∑(昨天可以转移到现在状态的所有可能的情况的