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

题目链接: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 }
时间: 2024-10-12 02:51:04

Codeforces 148D Bag of mice:概率dp 记忆化搜索的相关文章

Codeforces 148D Bag of mice (概率dp)

D. Bag of mice time limit per test:2 seconds memory limit per test:256 megabytes The dragon and the princess are arguing about what to do on the New Year's Eve. The dragon suggests flying to the mountains to watch fairies dancing in the moonlight, wh

Codeforces Div.301D Bad Luck Island(概率dp+记忆化搜索)

一道概率dp问题. 题目链接:http://codeforces.com/contest/540/problem/D 题目大意:一个岛上有r个石头,s个剪子,p个布,他们之间随机挑出两个相遇,如果不是相同物种,就会有一个消失,分别求出最后这座岛上只剩下一个物种的概率. 我们用dp[i][j][k]来存储i个石头,j个剪刀,k个布时,某物种的存活概率,共dp三次,算出三个物种分别的概率. 首先,我们需要把对应想求的物种概率初始化,这里以石头为例,那么对于i从1到r,不难理解dp[i][0][0]=

HDU - 5001 Walk(概率dp+记忆化搜索)

Walk 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 to an ad

【BZOJ1415】【Noi2005】聪聪和可可 概率DP 记忆化搜索

链接: #include <stdio.h> int main() { puts("转载请注明出处[辗转山河弋流歌 by 空灰冰魂]谢谢"); puts("网址:blog.csdn.net/vmurder/article/details/46457811"); } 题解: 记忆化搜索. f(i,j) 表示猫在 i .鼠在 j 时的期望. 然后显然它是拓扑的,然后先枚举起点n遍bfs算出 f(i,j) 时猫只走一步应该到哪个节点,然后对于 f(i,j) 枚

CF 148d Bag of mice 概率DP 好题

D. Bag of mice The dragon and the princess are arguing about what to do on the New Year's Eve. The dragon suggests flying to the mountains to watch fairies dancing in the moonlight, while the princess thinks they should just go to bed early. They are

CF 148D. Bag of mice[概率dp]

题目链接:http://codeforces.com/problemset/problem/148/D 题目大意:一袋子里有w个白老鼠,b个黑老鼠:A和B轮流抓老鼠(不放回),谁先抓到白老鼠,谁win:因为B粗鲁,每次抓完一只老鼠,会跑出来一只:A first: 求A win的概率: 题目分析: 此类概率dp的状态比较固定,dp(i , j )表示当前状态Awin的概率: 1:  dp[i][0],A win的概率为 1:dp[0][j] 概率为 0: 2:  dp[i][j]     如下四种

Codeforces 148D 一袋老鼠 Bag of mice | 概率DP 水题

除非特别忙,我接下来会尽可能翻译我做的每道CF题的题面! Codeforces 148D 一袋老鼠 Bag of mice | 概率DP 水题 题面 胡小兔和司公子都认为对方是垃圾. 为了决出谁才是垃圾,大哥拿来了一袋老鼠,其中有w只白老鼠和b只黑老鼠.胡小兔先抓,先抓到白老鼠的人赢. 每次学姐抓完老鼠之后,总会有另外一只老鼠从袋子里自己跑出来(这只老鼠不算任何人抓的),而胡小兔抓老鼠时则不会发生这样的事. 每次袋子里的每只老鼠被抓到的概率相等,当有一只老鼠跑出来的时候,每只老鼠跑出来的几率也相

11782 - Optimal Cut(树形DP+记忆化搜索)

题目链接:11782 - Optimal Cut 题意:按前序遍历给定一棵满二叉树,现在有k次,可以选k个节点,获得他们的权值,有两个条件: 1.一个节点被选了,他的子节点就不能选了. 2.最终选完后,根到所有叶子的路径上,都要有一个被选的节点. 思路:树形dp,dp[u][k]代表在结点u,可以选k个节点,那么就分两种情况 选u节点,dp[u][k] = node[u]; 选子节点之和,那么就把k次分配给左右孩子,dp[u][k] = max(dp[u][k], dp[u][i], dp[u]

[hihocoder 1033]交错和 数位dp/记忆化搜索

#1033 : 交错和 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 给定一个数 x,设它十进制展从高位到低位上的数位依次是 a0,?a1,?...,?an?-?1,定义交错和函数: f(x)?=?a0?-?a1?+?a2?-?...?+?(?-?1)n?-?1an?-?1 例如: f(3214567)?=?3?-?2?+?1?-?4?+?5?-?6?+?7?=?4 给定 输入 输入数据仅一行包含三个整数,l,?r,?k(0?≤?l?≤?r?≤?1018,?|k|