【算法每日一练]-动态规划 (篇9 概率dp)抓老鼠,抽奖概率

目录

题目:抓老鼠

思路: 

 题目:抽奖概率 


        

    

题目:抓老鼠

      

题意:一共有w只白鼠b只黑鼠,AB俩人轮流抓鼠,过程是这样的:A先抓一只然后B抓一只然后跑掉一只,抓到白鼠时此人获胜。我们设定两者都没抓到则B获胜,A先抓。问A获胜的概率?

              

思路: 

我们设置:dp[i][j]表示当前里面有i只白鼠j只黑鼠时  A先手的胜率。自然dp[0][i]=0,dp[i][0]=1,dp[i][1]=i/(i+1),我们要求dp[w][b]

        
dp[i][j]的概率是要么直接当局获胜i/(i+j),要么后局获胜。

dp[i][j]=1.0*i/(i+j)  

  
dp[i][j]+=j/(i+j)*(j-1)/(i+j-1)*  i /(i+j-2)*dp[i-1][j-2];//先手抓黑,后手抓黑,跑只白的情况

映射到dp[i-1][j-2]

     
dp[i][j]+=j/(i+j)*(j-1)/(i+j-1)*(j-2)/(i+j-2)*dp[i][j-3];//先手抓黑,后手抓黑,跑只黑的情况

映射到dp[i][j-3]

 

初始化:其实对于dp[i][1]的结果已经固定了,所以完全可以在双for循环(都是从1开始)的时候进行初始化的。 

#include <bits/stdc++.h>
using namespace std;
double dp[1005][1005];//dp[i][j]表示i只白鼠,j只黑鼠时,A先手的胜率
int main(){
	int w,b;
	cin>>w>>b;
	for(int i=1;i<=w;i++) dp[i][0]=1.0,dp[i][1]=1.0*i/(i+1);
	for(int i=1;i<=w;i++){
		for(int j=2;j<=b;j++){
			dp[i][j]=1.0*i/(i+j);//处理当前的获胜概率
			dp[i][j]+=1.0*j/(i+j)*(j-1)/(i+j-1)*i/(i+j-2)*dp[i-1][j-2];
			if(j>=3) dp[i][j]+=1.0*j/(i+j)*(j-1)/(i+j-1)*(j-2)/(i+j-2)*dp[i][j-3];
		}
	}
	printf("%.9lf",dp[w][b]);
	return 0;
}

        

        

 题目:抽奖概率 

有一个抽奖活动:抽一个2元,可能会抽出1,2,3,4元(概率相等)。

问抽n次,亏本的概率是多少(奖金小于本金)?纯赚超过一半本金的概率是多少

(分数时候输出最简分数)

输入:2              输出:3/16

                                   3/16

思路:

直接求概率不太容易。而且还要最简分数,那么就转化乘求方案数就会具体很多。

设置dp[i][j]表示已经抽奖i次且拿到了总额为j的方案数.dp[i][j]+=dp[i-1][j-1,j-2,j-3,j-4]

最后的最简分数可以使用gcd函数完成。

初始化:这种初始化有点多余,第一轮的循环完全就是做样子,可以直接从第二轮开始。

#include <bits/stdc++.h>
using namespace std;
int dp[40][160],n;
int gcd(int a,int b){return b==0?a:gcd(b,a%b);}

int main(){
	cin>>n;
	dp[1][1]=dp[1][2]=dp[1][3]=dp[1][4]=1;
	for(int i=1;i<=n;i++)
	for(int j=i;j<=4*n;j++){
		for(int k=1;k<=4;k++)
			if(j>k) dp[i][j]+=dp[i-1][j-k];
	}
	int sum1=0,sum2=0,sum=1;
	for(int i=n;i<2*n;i++)
		sum1+=dp[n][i];
	for(int i=3*n+1;i<=4*n;i++)
		sum2+=dp[n][i];
	for(int i=1;i<=n;i++)
		sum*=4;
	int k=gcd(sum1,sum);
	cout<<sum1/k<<"/"<<sum/k<<'\n';
	k=gcd(sum2,sum);
	cout<<sum2/k<<"/"<<sum/k<<'\n';

}

   

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值