Codeforces 148D Bag of mice:概率dp 记忆化搜索

本文解析 CodeForces 148D 题目,该题涉及游戏中的概率计算。通过动态规划方法求解公主赢得游戏的概率,并给出记忆化搜索和 for 循环两种实现方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接:http://codeforces.com/problemset/problem/148/D

题意:

  一个袋子中有w只白老鼠,b只黑老鼠。

  公主和龙轮流从袋子里随机抓一只老鼠出来,不放回,公主先拿。

  公主每次抓一只出来。龙每次在抓一只出来之后,会随机有一只老鼠跳出来(被龙吓的了。。。)。

  先抓到白老鼠的人赢。若两人最后都没有抓到白老鼠,则龙赢。

  问你公主赢的概率。

 

题解:

  表示状态:

    dp[i][j] = probability to win(当前公主先手,公主赢的概率)

    i:剩i只白老鼠

    j:剩j只黑老鼠

 

  找出答案:

    ans = dp[w][b]

 

  边界条件:

    if i==0 dp[i][j] = 0 (没有白老鼠了,不可能赢)

    else if j==0 dp[i][j] = 1 (有且只有白老鼠,一定赢)

    else if j==1 dp[i][j] = i/(i+1) (如果公主拿了黑老鼠,那么龙一定会拿到白老鼠,公主输。所以公主一下就要拿到白老鼠)

 

 

  如何转移:

    对于dp[i][j],有两种赢的方法:

      (1)公主在这个回合一次就抓到了白老鼠。

      (2)公主和龙都各抓了一只黑老鼠,然后公主在下一个回合赢了。

    P(一次就抓到了白老鼠) = i/(i+j)

    P(进入下个回合,即两人都抓到黑老鼠) = P(公主抓到黑老鼠) * P(龙抓到黑老鼠) = j/(i+j) * (j-1)/(i+j-1)

    所以dp[i][j] = P(一次就抓到了白老鼠) + P(进入下个回合) * P(在下个回合赢)

    

    那么考虑下个回合可能的状态。

    因为公主和龙都已经抓走了两只黑老鼠,那么下个回合取决于跳出来的老鼠,有三种可能:

      (1)跳出来白老鼠

      (2)跳出来黑老鼠

      (3)老鼠已经抓完了,没有老鼠跳出来

    对于情况(3),原状态(i,j)只可能为:(1,1) , (0,2) , (2,0),均包含在边界条件中,所以不作考虑。

    剩下两种情况的可能性:

      (1)P(跳出来白老鼠) = i/(i+j-2) (i>=1 and j>=2)

      (2)P(跳出来黑老鼠) = (j-2)/(i+j-2) (j>=3)

    所以P(在下个回合赢) = P(跳出来白老鼠) * dp[i-1][j-2] + P(跳出来黑老鼠) * dp[i][j-3]

 

    总方程:

      nex = 0

      if i>=1 and j>=2 nex += i/(i+j-2)*dp[i-1][j-2]

      if j>=3 nex += (j-2)/(i+j-2)*dp[i][j-3]

      dp[i][j] = i/(i+j) + j/(i+j) * (j-1)/(i+j-1) * nex

 

  另外,这道题的题解有两个版本,一种记忆化搜索,一种for循环版,都差不多。

 

AC Code(记忆化搜索):

 1 // state expression:
 2 // dp[i][j] = probability to win
 3 // i: i white mice
 4 // j: j black mice
 5 //
 6 // find the answer:
 7 // ans = dp[w][b]
 8 //
 9 // transferring:
10 // if i>=1 and j>=2 nex += i/(i+j-2)*dp[i-1][j-2]
11 // if j>=3 nex += (j-2)/(i+j-2)*dp[i][j-3]
12 // dp[i][j] = i/(i+j) + j/(i+j) * (j-1)/(i+j-1) * nex
13 //
14 // boundary:
15 // if i==0 dp[i][j] = 0
16 // if j==0 dp[i][j] = 1
17 // if j==1 dp[i][j] = i/(i+1)
18 #include <iostream>
19 #include <stdio.h>
20 #include <string.h>
21 #define MAX_N 1005
22 
23 using namespace std;
24 
25 int w,b;
26 bool vis[MAX_N][MAX_N];
27 double ans;
28 double dp[MAX_N][MAX_N];
29 
30 double dfs(int i,int j)
31 {
32     if(vis[i][j]) return dp[i][j];
33     vis[i][j]=true;
34     if(i==0) return dp[i][j]=0;
35     if(j==0) return dp[i][j]=1;
36     if(j==1) return dp[i][j]=(double)i/(i+1);
37     double nex=0;
38     nex+=(double)i/(i+j-2)*dfs(i-1,j-2);
39     if(j>=3) nex+=(double)(j-2)/(i+j-2)*dfs(i,j-3);
40     return dp[i][j]=(double)i/(i+j)+(double)j/(i+j)*(j-1)/(i+j-1)*nex;
41 }
42 
43 void read()
44 {
45     cin>>w>>b;
46 }
47 
48 void solve()
49 {
50     memset(vis,false,sizeof(vis));
51     ans=dfs(w,b);
52 }
53 
54 void print()
55 {
56     printf("%.9f\n",ans);
57 }
58 
59 int main()
60 {
61     read();
62     solve();
63     print();
64 }

 

AC Code(for循环):

 

 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <string.h>
 4 #define MAX_N 1005
 5 
 6 using namespace std;
 7 
 8 int w,b;
 9 double ans;
10 double dp[MAX_N][MAX_N];
11 
12 void read()
13 {
14     cin>>w>>b;
15 }
16 
17 void solve()
18 {
19     memset(dp,0,sizeof(dp));
20     for(int i=0;i<=w;i++)
21     {
22         for(int j=0;j<=b;j++)
23         {
24             if(i==0)
25             {
26                 dp[i][j]=0;
27                 continue;
28             }
29             if(j==0)
30             {
31                 dp[i][j]=1;
32                 continue;
33             }
34             if(j==1)
35             {
36                 dp[i][j]=(double)i/(i+1);
37                 continue;
38             }
39             double nex=(double)i/(i+j-2)*dp[i-1][j-2];
40             if(j>=3) nex+=(double)(j-2)/(i+j-2)*dp[i][j-3];
41             dp[i][j]=(double)i/(i+j)+(double)j/(i+j)*(j-1)/(i+j-1)*nex;
42         }
43     }
44 }
45 
46 void print()
47 {
48     printf("%.9f\n",dp[w][b]);
49 }
50 
51 int main()
52 {
53     read();
54     solve();
55     print();
56 }

 

通达信行情API是金融数据提供商通达信(TongDaXin)为开发者和金融机构提供的接口服务,用于获取实时及历史的股票、期货、期权等金融市场数据。这个API允许用户在自己的应用程序中集成通达信的数据服务,实现个性化数据分析、交易策略开发等功能。 1. **API基本概念** - **API**:Application Programming Interface,应用程序编程接口,是软件之间交互的一种方式,提供预定义的函数和方法,使得其他软件能够调用特定功能。 - **通达信**:国内知名的金融终端软件提供商,提供股票、期货、基金等市场数据,以及交易服务。 2. **通达信API的功能** - **实时行情**:获取股票、期货、期权等市场的实时报价信息,包括最新价、涨跌额、涨跌幅、成交量等。 - **历史数据**:获取历史交易日的K线数据、分时数据、交易量等信息,支持自定义时间段查询。 - **深度数据**:获取买卖盘口的五档报价和成交量,有助于分析市场买卖意愿。 - **资讯信息**:获取公告、研报、新闻等市场资讯。 - **交易委托**:通过API进行交易下单、撤单等操作,实现自动化交易。 3. **TdxHqApi** - **TdxHqApi** 是通达信行情API的具体实现,它包含了调用通达信数据服务的各种函数和类,如获取股票列表、获取实时行情、获取历史数据等。 - 开发者需要按照API文档的指示,导入TdxHqApi库,然后通过调用相应的函数来获取所需数据。 4. **使用步骤** - **安装**:下载并安装通达信API的SDK,通常包括头文件和动态链接库。 - **初始化**:在代码中实例化API对象,进行连接设置,如服务器地址、端口号等。 - **连接**:连接到通达信服务器,进行身份验证。 - **数据请求**:调用对应的API函数,例如`GetS
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值