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(记忆化搜索):
// state expression:
// dp[i][j] = probability to win
// i: i white mice
// j: j black mice
//
// find the answer:
// ans = dp[w][b]
//
// transferring:
// 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
//
// boundary:
// if i==0 dp[i][j] = 0
// if j==0 dp[i][j] = 1
// if j==1 dp[i][j] = i/(i+1)
#include <iostream>
#include <stdio.h>
#include <string.h>
#define MAX_N 1005 using namespace std; int w,b;
bool vis[MAX_N][MAX_N];
double ans;
double dp[MAX_N][MAX_N]; double dfs(int i,int j)
{
if(vis[i][j]) return dp[i][j];
vis[i][j]=true;
if(i==) return dp[i][j]=;
if(j==) return dp[i][j]=;
if(j==) return dp[i][j]=(double)i/(i+);
double nex=;
nex+=(double)i/(i+j-)*dfs(i-,j-);
if(j>=) nex+=(double)(j-)/(i+j-)*dfs(i,j-);
return dp[i][j]=(double)i/(i+j)+(double)j/(i+j)*(j-)/(i+j-)*nex;
} void read()
{
cin>>w>>b;
} void solve()
{
memset(vis,false,sizeof(vis));
ans=dfs(w,b);
} void print()
{
printf("%.9f\n",ans);
} int main()
{
read();
solve();
print();
}
AC Code(for循环):
#include <iostream>
#include <stdio.h>
#include <string.h>
#define MAX_N 1005 using namespace std; int w,b;
double ans;
double dp[MAX_N][MAX_N]; void read()
{
cin>>w>>b;
} void solve()
{
memset(dp,,sizeof(dp));
for(int i=;i<=w;i++)
{
for(int j=;j<=b;j++)
{
if(i==)
{
dp[i][j]=;
continue;
}
if(j==)
{
dp[i][j]=;
continue;
}
if(j==)
{
dp[i][j]=(double)i/(i+);
continue;
}
double nex=(double)i/(i+j-)*dp[i-][j-];
if(j>=) nex+=(double)(j-)/(i+j-)*dp[i][j-];
dp[i][j]=(double)i/(i+j)+(double)j/(i+j)*(j-)/(i+j-)*nex;
}
}
} void print()
{
printf("%.9f\n",dp[w][b]);
} int main()
{
read();
solve();
print();
}
Codeforces 148D Bag of mice:概率dp 记忆化搜索的更多相关文章
- codeforces 148D Bag of mice(概率dp)
题意:给你w个白色小鼠和b个黑色小鼠,把他们放到袋子里,princess先取,dragon后取,princess取的时候从剩下的当当中任意取一个,dragon取得时候也是从剩下的时候任取一个,但是取完 ...
- Codeforces 148D Bag of mice 概率dp(水
题目链接:http://codeforces.com/problemset/problem/148/D 题意: 原来袋子里有w仅仅白鼠和b仅仅黑鼠 龙和王妃轮流从袋子里抓老鼠. 谁先抓到白色老师谁就赢 ...
- CodeForces 398B 概率DP 记忆化搜索
题目:http://codeforces.com/contest/398/problem/B 有点似曾相识的感觉,记忆中上次那个跟这个相似的 我是用了 暴力搜索过掉的,今天这个肯定不行了,dp方程想了 ...
- HDU 5001 概率DP || 记忆化搜索
2014 ACM/ICPC Asia Regional Anshan Online 给N个点,M条边组成的图,每一步能够从一个点走到相邻任一点,概率同样,问D步后没走到过每一个点的概率 概率DP 測 ...
- 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 t ...
- CF 148D Bag of mice 概率dp 难度:0
D. Bag of mice time limit per test 2 seconds memory limit per test 256 megabytes input standard inpu ...
- codeforce 148D. Bag of mice[概率dp]
D. Bag of mice time limit per test 2 seconds memory limit per test 256 megabytes input standard inpu ...
- 抓老鼠 codeForce 148D - Bag of mice 概率DP
设dp[i][j]为有白老鼠i只,黑老鼠j只时轮到公主取时,公主赢的概率. 那么当i = 0 时,为0 当j = 0时,为1 公主可直接取出白老鼠一只赢的概率为i/(i+j) 公主取出了黑老鼠,龙必然 ...
- hdu3559 Frost Chain (概率dp+记忆化搜索)
Problem Description In the unimaginable popular DotA game, the hero Lich has a wonderful skill: Fros ...
随机推荐
- 数据结构之---C语言实现图的数组(邻接矩阵)存储表示
//图的数组(邻接矩阵)存储表示 #include <stdio.h> #include <stdlib.h> #define MAX_VEX_NUM 50 typedef c ...
- UVA - 10895 Matrix Transpose
UVA - 10895 Matrix Transpose Time Limit:3000MS Memory Limit:Unknown 64bit IO Format:%lld & % ...
- centos网络配置实例
1.配置DNS vim /etc/resolv.conf nameserver 192.168.0.1 nameserver 8.8.8.8 nameserver 8.8.4.4 2.配置网关 r ...
- Python 2.7 升 3.4
Ubuntu 14.04 已经安装有python3.4.0 命令行使用python3 或者创建链接即可 ln -s /usr/bin/python3 /usr/bin/python [推荐此方法,然后 ...
- JVM学习02-GC算法与种类
1. GC 简单介绍 GC(Garbage Collection) 是垃圾收集的简写,GC机制是java中一个比較重要的概念.java的内存管理提供了内存的分配和释放.内存处理是程序编写人员非常eas ...
- 利用xlrd模块实现Python读取Excel文档
# -*- coding: cp936 -*- #python读取excel import xlrd def main(): xls=xlrd.open_workbook("d:\\11.x ...
- A和B是好友,他们经常在空闲时间聊天,A的空闲时间为[a1 ,b1 ],[a2 ,b2 ]..[ap ,bp ]。B的空闲时间是[c1 +t,d1 +t]..[cq +t,dq +t],这里t为B的起床时间。这些时间包括了边界点。B的起床时间为[l,r]的一个时刻。若一个起床时间能使两人在任意时刻聊天,那么这个时间就是合适的,问有多少个合适的起床时间?
// ConsoleApplication5.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include<vector> ...
- C语言序列点问题总结(大多数高等教育C语言教学课程的漏洞)
C语言序列点总结 2013年11月21于浙大华家池 C 语言副作用: (side effect)是指对数据对象或者文件的修改. 例如,语句 v = 99;的副作用是把 v 的值修改成 99. C语言序 ...
- linux SPI驱动——spidev之driver(六)
一: spidev_init注册spidev 1: static int __init spidev_init(void) 2: { 3: int status; 4: 5: /* Claim o ...
- Color.js 方便修改颜色值
这并不是npm上比较活跃的clolr包的中文文档,不过它在最后提到了: The API was inspired by color-js. Manipulation functions by CSS ...