动态规划-概率DP

news2024/11/26 15:47:41

Bag of mice

题面翻译

https://www.luogu.com.cn/problem/CF148D

袋子里有 w w w 只白鼠和 b b b 只黑鼠 ,A和B轮流从袋子里抓,谁先抓到白色谁就赢。A每次随机抓一只,B每次随机抓完一只之后会有另一只随机老鼠跑出来。如果两个人都没有抓到白色则B赢。A先抓,问A赢的概率。

输入

一行两个数 w , b w,b w,b

输出

A赢的概率,误差 1 0 − 9 10^{-9} 109 以内。

数据范围

0 ≤ w , b ≤ 1000 0\le w,b\le 1000 0w,b1000

题目描述

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 desperate to come to an amicable agreement, so they decide to leave this up to chance.

They take turns drawing a mouse from a bag which initially contains $ w $ white and $ b $ black mice. The person who is the first to draw a white mouse wins. After each mouse drawn by the dragon the rest of mice in the bag panic, and one of them jumps out of the bag itself (the princess draws her mice carefully and doesn’t scare other mice). Princess draws first. What is the probability of the princess winning?

If there are no more mice in the bag and nobody has drawn a white mouse, the dragon wins. Mice which jump out of the bag themselves are not considered to be drawn (do not define the winner). Once a mouse has left the bag, it never returns to it. Every mouse is drawn from the bag with the same probability as every other one, and every mouse jumps out of the bag with the same probability as every other one.

输入格式

The only line of input data contains two integers $ w $ and $ b $ ( $ 0<=w,b<=1000 $ ).

输出格式

Output the probability of the princess winning. The answer is considered to be correct if its absolute or relative error does not exceed $ 10^{-9} $ .

样例 #1

样例输入 #1

1 3

样例输出 #1

0.500000000

样例 #2

样例输入 #2

5 5

样例输出 #2

0.658730159

提示

Let’s go through the first sample. The probability of the princess drawing a white mouse on her first turn and winning right away is 1/4. The probability of the dragon drawing a black mouse and not winning on his first turn is 3/4 * 2/3 = 1/2. After this there are two mice left in the bag — one black and one white; one of them jumps out, and the other is drawn by the princess on her second turn. If the princess’ mouse is white, she wins (probability is 1/2 * 1/2 = 1/4), otherwise nobody gets the white mouse, so according to the rule the dragon wins.

思路

本题是dp算概率:

状态表示:f[i][j]表示当前袋中有i只白鼠j只黑鼠时,A获胜的概率

起点:

  • f[0][i]=0 袋子中没有白鼠,A获胜的概率为0
  • f[i][0]=1袋子中全是白鼠,A获胜的概率为1

终点:f[w][b]

状态转移:

  • 先手拿到白鼠: f [ i ] [ j ] + = i i + j f[i][j]+=\frac{i}{i+j} f[i][j]+=i+ji
  • 先手拿到黑鼠:
    • 后手拿到白鼠:先手获胜概率为0,即 f [ i ] [ j ] + = 0 f[i][j]+=0 f[i][j]+=0
    • 后手拿到黑鼠:
      • 跑了白鼠: f [ i ] [ j ] + = j i + j ∗ j − 1 i + j − 1 ∗ i i + j − 2 ∗ f [ i − 1 ] [ j − 2 ] f[i][j]+=\frac{j}{i+j}*\frac{j-1}{i+j-1}*\frac{i}{i+j-2}*f[i-1][j-2] f[i][j]+=i+jji+j1j1i+j2if[i1][j2]
      • 跑了黑鼠: f [ i ] [ j ] + = j i + j ∗ j 1 i + j − 1 ∗ j − 2 i + j − 2 ∗ f [ i ] [ j − 3 ] f[i][j]+=\frac{j}{i+j}*\frac{j1}{i+j-1}*\frac{j-2}{i+j-2}*f[i][j-3] f[i][j]+=i+jji+j1j1i+j2j2f[i][j3]

代码

线性递推:

#include <bits/stdc++.h>

#define int long long
using namespace std;


signed main() {
#ifndef ONLINE_JUDGE
    freopen("test.in", "r", stdin);
    freopen("test.out", "w", stdout);
#endif
    int w, b;
    cin >> w >> b;
    vector<vector<double>> f(w + 1, vector<double>(b + 1));
    //fij表示袋子里有i只白鼠,j只黑鼠时A获胜的概率
    for (int i = 1; i <= b; i++) f[0][i] = 0;
    for (int i = 1; i <= w; i++) f[i][0] = 1;

    for (int i = 1; i <= w; i++) {
        for (int j = 1; j <= b; j++) {
            f[i][j] += 1.0 * i / (i + j);
            if (i >= 1 && j >= 2)
                f[i][j] += 1.0 * j / (i + j) * (j - 1) / (i + j - 1) * i / (i + j - 2) * f[i - 1][j - 2];
            if (j >= 3)
                f[i][j] += 1.0 * j / (i + j) * (j - 1) / (i + j - 1) * (j - 2) / (i + j - 2) * f[i][j - 3];
        }
    }
    printf("%.10f", f[w][b]);

    return 0;
}

记忆化搜索:

#include <bits/stdc++.h>

#define int long long
using namespace std;

const int N = 1010;
double f[N][N];

double dfs(int i, int j) {
    if (f[i][j]) return f[i][j];
    if (i == 0) return f[i][j] = 0;
    if (j == 0) return f[i][j] = 1.0;
    f[i][j] += 1.0 * i / (i + j);//先白
    if (i >= 1 && j >= 2)
        f[i][j] += 1.0 * j / (i + j) * (j - 1) / (i + j - 1) * i / (i + j - 2) * dfs(i - 1, j - 2);
    if (j >= 3)
        f[i][j] += 1.0 * j / (i + j) * (j - 1) / (i + j - 1) * (j - 2) / (i + j - 2) * dfs(i, j - 3);
    return f[i][j];
}

signed main() {
#ifndef ONLINE_JUDGE
    freopen("test.in", "r", stdin);
    freopen("test.out", "w", stdout);
#endif
    int w, b;
    cin >> w >> b;
    double t = dfs(w, b);
    std::printf("%.10f", t);
    return 0;
}

FootBall

题意

https://vjudge.csgrandeur.cn/problem/POJ-3071

有2^n支球队比赛,每次和相邻的球队踢,两两淘汰,给定任意两支球队相互踢赢的概率,求最后哪只球队最可能夺冠

输入

2
0.0 0.1 0.2 0.3
0.9 0.0 0.4 0.5
0.8 0.6 0.0 0.6
0.7 0.5 0.4 0.0
-1

输出

2

思路

计算每个球队的获胜概率,取概率得到max的队伍即为答案

状态表示:f[i][j]表示在第i轮中,第j队获胜的概率

起点:f[0][i]=1表示第0轮全部都获胜

状态转移: f [ i ] [ j ] + = f [ i − 1 ] [ j ] ∗ f [ i − 1 ] [ k ] ∗ p [ j ] [ k ] f[i][j]+=f[i-1][j]*f[i-1][k]*p[j][k] f[i][j]+=f[i1][j]f[i1][k]p[j][k]

解释:

如果在第i轮中,j队与k队比赛,说明在i-1轮中,两队都获胜了, 计算 f [ i ] [ j ] f[i][j] f[i][j]还需要乘上j赢k的概率

我们在枚举第i轮,j队可以和哪些队伍相遇的时候,也就是找出第i-1轮获胜的邻近球队,可以使用如下技巧:

image-20230530133521948

注意,POJ使用cin会超时,使用scanf需要加上cstdio

代码

#include <iostream>
#include <cstdio>

#define int long long
using namespace std;

const int N = 130;
double p[N][N];
double f[N][N];
int n, m;

void solve() {
    m = 1 << n;
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < m; j++) {
            scanf("%lf", &p[i][j]);
        }
    }
    for (int i = 0; i <= n; i++) {
        for (int j = 0; j < m; j++) {
            f[i][j] = 0;
        }
    }
    for (int i = 0; i < m; i++) f[0][i] = 1;

    for (int i = 1; i <= n; i++) { //多少场
        for (int j = 0; j < m; j++) {//第j个队伍
            for (int k = 0; k < m; k++) {//对手队伍
                int x = (j >> (i - 1)) ^ 1;
                int y = (k >> (i - 1));
                if (x == y) {
                    f[i][j] += f[i - 1][j] * f[i - 1][k] * p[j][k];
                }
            }
        }
    }
    int idx = 0;
    double max = -1;
    for (int i = 0; i < m; i++) {
        if (f[n][i] > max) {
            idx = i + 1;
            max = f[n][i];
        }
    }
    cout << idx << endl;
}

signed main() {
#ifndef ONLINE_JUDGE
    freopen("test.in", "r", stdin);
    freopen("test.out", "w", stdout);
#endif
    while (scanf("%lld", &n), n != -1) solve();
    return 0;
}

Jon and Orbs

题面翻译

https://www.luogu.com.cn/problem/CF768D

一个人要取   N   \,N\, N件物品,一天只能取一件物品,但不能确定取到的是什么物品,求最少需要在第几天,取完这   N   \,N\, N件物品的概率不小于   p 2000   \,\dfrac{p}{2000}\, 2000p,有   q   \,q\, q组询问,每组询问给定这个   p   \,p\, p

题目描述

Jon Snow is on the lookout for some orbs required to defeat the white walkers. There are $ k $ different types of orbs and he needs at least one of each. One orb spawns daily at the base of a Weirwood tree north of the wall. The probability of this orb being of any kind is equal. As the north of wall is full of dangers, he wants to know the minimum number of days he should wait before sending a ranger to collect the orbs such that the probability of him getting at least one of each kind of orb is at least , where $ ε<10^{-7} $ .

To better prepare himself, he wants to know the answer for $ q $ different values of $ p_{i} $ . Since he is busy designing the battle strategy with Sam, he asks you for your help.

输入格式

First line consists of two space separated integers $ k $ , $ q $ ( $ 1<=k,q<=1000 $ ) — number of different kinds of orbs and number of queries respectively.

Each of the next $ q $ lines contain a single integer $ p_{i} $ ( $ 1<=p_{i}<=1000 $ ) — $ i $ -th query.

输出格式

Output $ q $ lines. On $ i $ -th of them output single integer — answer for $ i $ -th query.

样例 #1

样例输入 #1

1 1
1

样例输出 #1

1

样例 #2

样例输入 #2

2 2
1
2

样例输出 #2

2
2

思路

概率dp

状态表示:f[i][j]表示前i天,取到了j个不同的物品的概率

状态转移:

  • 第i-1天已经取到了j个物品,则第i天应该取这j个物品中任意一个: f [ i ] [ j ] + = f [ i − 1 ] [ j ] ∗ j k f[i][j]+=f[i-1][j]*\frac{j}{k} f[i][j]+=f[i1][j]kj
  • 第i-1天取到了j-1个物品,第i天从剩下的 n − ( j − 1 ) n-(j-1) n(j1)里面取一个: f [ i ] [ j ] + = f [ i − 1 ] [ j − 1 ] ∗ n − j + 1 k f[i][j]+=f[i-1][j-1]*\frac{n-j+1}{k} f[i][j]+=f[i1][j1]knj+1

一开始可以先把数组开很大,例如10000,然后试试极限数据也就是取1000个物品需要多少天,跑完之后发现只需要7274天,因此数组开到7500就可以了。

极限数据

1000 1
1000

代码

#include <bits/stdc++.h>

#define int long long
using namespace std;

const int N = 7500, M = 1010;
double f[N][M];


signed main() {
#ifndef ONLINE_JUDGE
    freopen("test.in", "r", stdin);
    freopen("test.out", "w", stdout);
#endif
    int k, q;
    cin >> k >> q;
    f[0][0] = 1.0;
    for (int i = 1; i < N; i++) {
        for (int j = 1; j <= k; j++) {
            f[i][j] += 1.0 * f[i - 1][j - 1]  * (k - j + 1) / k;
            f[i][j] += 1.0 * f[i - 1][j]  * j / k;
        }
    }
    while (q--) {
        double p;
        cin >> p;
        double t = 1.0 * p / 2000;
        for (int i = 1; i < N; i++) {
            if (f[i][k] > t) {
                cout << i << endl;
                break;
            }
        }
    }
    return 0;
}

Collecting Bugs

题目

一个软件有s个子系统,会产生n种bug,某人一天发现一个bug,这个bug属于一个子系统,属于一个分类
每个bug属于某个子系统的概率是1/s,属于某种分类的概率是1/n
问:发现n种bug,s个子系统都发现bug的期望天数

思路

状态表示:f[i][j]表示已经找了i种bug,j个子系统的bug,达到目标状态的期望天数

起始状态:f[n][s]=0,答案f[0][0]

状态转移:

  • f[i][j]:发现一个bug属于已经有的i个分类,j个系统,概率为 p 1 = ( i / n ) ∗ ( j / s ) p_1=(i/n)*(j/s) p1=(i/n)(j/s)
  • f[i][j+1]:发现一个bug属于已有的分类,不属于已有的系统,概率为: p 2 = ( i / n ) ∗ ( 1 − j s ) p_2=(i/n)*(1-\frac{j}{s}) p2=(i/n)(1sj)
  • f[i+1][j]:发现一个bug不属于已有分类,属于已有的系统,概率为: p 3 = ( 1 − i n ) ∗ ( j / s ) p_3=(1-\frac{i}{n})*(j/s) p3=(1ni)(j/s)
  • f[i+1][j+1]:发现一个bug不属于已有分类,不属于已有系统,概率为: p 4 = ( 1 − i n ) ∗ ( 1 − j s ) p_4=(1-\frac{i}{n})*(1-\frac{j}{s}) p4=(1ni)(1sj)

因此: f [ i ] [ j ] = f [ i ] [ j ] ∗ p 1 + f [ i ] [ j + 1 ] ∗ p 2 + f [ i + 1 ] [ j ] ∗ p 3 + f [ i + 1 ] [ j + 1 ] ∗ p 4 + 1 f[i][j]=f[i][j]*p_1+f[i][j+1]*p_2+f[i+1][j]*p_3+f[i+1][j+1]*p_4+1 f[i][j]=f[i][j]p1+f[i][j+1]p2+f[i+1][j]p3+f[i+1][j+1]p4+1

移项,将 f [ i ] [ j ] f[i][j] f[i][j]放到同一侧,除去 1 − p 1 1-p_1 1p1得:

f [ i ] [ j ] = ( f [ i ] [ j + 1 ] ∗ p 2 + f [ i + 1 ] [ j ] ∗ p 3 + f [ i + 1 ] [ j + 1 ] ∗ p 4 + 1 ) / ( 1 − p 1 ) f[i][j]=(f[i][j+1]*p_2+f[i+1][j]*p_3+f[i+1][j+1]*p_4+1)/(1-p_1) f[i][j]=(f[i][j+1]p2+f[i+1][j]p3+f[i+1][j+1]p4+1)/(1p1)

代码

#include <iostream>
#include <vector>
#include <cstdio>
#define int long long
using namespace std;


signed main() {
#ifndef ONLINE_JUDGE
    freopen("test.in", "r", stdin);
    freopen("test.out", "w", stdout);
#endif
    int n, s;
    cin >> n >> s;
    vector<vector<double> > f(n + 2, vector<double>(s + 2));
    f[n][s] = 0;
    for (int i = n; i >= 0; i--) {
        for (int j = s; j >= 0; j--) {
            if (i == n && j == s) continue;
            double p1 = 1.0 * i / n * j / s;
            double p2 = 1.0 * i / n * (s - j) / s;
            double p3 = 1.0 * (n - i) / n * j / s;
            double p4 = 1.0 * (n - i) / n * (s - j) / s;
            f[i][j] = (f[i][j + 1] * p2 + f[i + 1][j] * p3 + f[i + 1][j + 1] * p4 + 1) / (1 - p1);
        }
    }
    printf("%10f",f[0][0]);
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/608300.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【小沐学GIS】基于Cesium实现三维数字地球Earth(CesiumJS入门安装)

文章目录 1、简介1.1 平台1.1.1 Cesium ion1.1.2 CesiumJS1.1.3 Cesium for Unity1.1.4 Cesium for Unreal1.1.4 Cesium for Omniverse1.1.5 Cesium for O3DE 1.2 支持的数据格式 2、CesiumJS安装3、代码测试3.1 安装node3.2 安装依赖项3.3 运行测试示例3.4 注册获取token 4、扩…

常见的前端框架

随着前端行业的发展&#xff0c;前端框架越来越多出现&#xff0c;为我们的项目开发工作带来了极大的便利&#xff0c;那目前主流的前端框架有哪些呢&#xff1f; 工作中我们常用的前端框架有vue框架、React框架、Bootstrap框架、Angular框架等&#xff0c;下面给大家简单介绍…

【AI绘图】二、stable diffusion环境准备与安装

前一篇&#xff1a;一、stable diffusion的发展史 放一张SD的效果图 硬件配置要求 Stable Diffusion是使用显卡生成图片&#xff0c;对电脑硬件有一定要求。 电脑配置最核心的关键点&#xff1a;看显卡、看内存、看硬盘、看 CPU。 显卡&#xff1a;N 卡&#xff08;英伟达 N…

基于内点法求解最优潮流研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

Spring源码(二)— AbstractApplicationContext

上一篇文章简单的介绍了一下Spring框架大体的一个执行流程&#xff0c;整个专栏的内容也会根据第一篇序言中的流程图一步一步的向下梳理&#xff0c;并会慢慢补充更多的细节进去。 Test 创建ClassPathXmlApplicationContext来解析xml。 public class Test {public static vo…

剖析 OpenShift 中的 DNS

深入分析 OpenShift 内部 DNS OpenShift 中的DNS 相关组件及其配置1.1 Pod 中的 DNS 配置1.2 Pod 所在宿主机上的 DNS 配置及服务1.2.1 resolv.conf 文件 DNS 配置DNS 查询流程为什么需要内部 DNS&#xff1f; 本文基于 OpenShift 3.11&#xff0c;Kubernetes 1.11 进行测试 O…

2023/6/4周报

目录 摘要 论文阅读 1、标题和现存问题 2、使用GNN进行文本分类 3、INDUCT-GCN 4、实验准备 5、实验结果 深度学习 1、时空图的种类 2、图在环境中的应用 3、STGNN 总结 摘要 本周在论文阅读上&#xff0c;阅读了一篇InducT-GCN:归纳图卷积文本分类网络的论文。基…

python-pandas按各种时间统计和案例

使用到的库 pandas、matplotlib、numpy 使用到的函数 df.resample(“H”).sum() 参数 B business day frequency C custom business day frequency (experimental) D calendar day frequency W weekly frequency M month end frequency BM business month end frequency CBM…

【奶奶看了都会】云服务器ChatGLM模型fine-tuning微调,让你拥有自己的知识库

1.背景 大家好啊&#xff0c;上次给大家写了ChatGLM-6B的部署使用教程&#xff0c;【奶奶看了都会】云服务器部署开源ChatGLM-6B&#xff0c;让你拥有自己的ChatGPT 但是因为模型比较小的问题&#xff0c;所以日常工作中可能用不上。而且大家更希望的是模型能训练自己的数据&…

【Python Bokeh】零基础也能轻松掌握的学习路线与参考资料

Python Bokeh是一款为开发者提供数据可视化的Python库。它可以帮助开发者轻松地创建交互式网页应用程序&#xff0c;而无需编写大量的JavaScript代码。Bokeh支持各种绘图类型和工具&#xff0c;包括线图、散点图、条形图等。Python Bokeh非常适合在大数据分析、商业智能和数据科…

chatgpt赋能python:Python去除重复元素的几种方法

Python去除重复元素的几种方法 在Python编程中&#xff0c;去除列表、集合、字典等数据结构中的重复元素是一个常见的操作。本文将介绍Python中去除重复元素的几种方法&#xff0c;并分析它们的优缺点。 方法一&#xff1a;使用set去重 Set是Python中的一种集合类数据结构&a…

17_Linux根文件简介与Busybox构建文件系统

目录 根文件系统简介 文件目录简介 BusyBox简介 编译BusyBox构建根文件系统 修改Makefile添加编译器 busybox中文字符支持 配置 busybox 编译busybox 向根文件系统添加lib库 向rootfs的“usr/lib”目录添加库文件 创建其他文件夹 根文件系统初步测试 根文件系统简介…

Unity制作二次元卡通渲染角色材质——3、高光反射与ILM贴图

Unity制作二次元材质角色 回到目录 大家好&#xff0c;我是阿赵。 这里继续来讲二次元角色的材质。上次讲了光影的色阶化问题&#xff0c;这次继续讲光照模型效果的问题。 之前我们说过&#xff0c;光照模型的最后效果是&#xff1a; 环境色漫反射高光反射。 这里我们可以先忽略…

【嵌入式系统】思考题复习

嵌入式系统思考题 0. 名词解释1. 嵌入式系统概述2. ARM处理器体系结构3. ARM指令集4. S5PV210微处理器与接口5. ARM-Linux内核6. 嵌入式Linux文件系统7. 嵌入式Linux系统移植及调试8. 设备驱动程序设计9. QT图形界面应用程序开发基础10. SQLite数据库11. 嵌入式系统的开发设计案…

Qt6.5.1LTS搭建Android开发环境填坑

Qt6第二个LTS出来了&#xff0c;周日找时间安装并测试了Qt6.5LTS&#xff0c;安装我是按我之前的一个博客记录来做的&#xff0c;用的是国内境像&#xff0c;顺利快速安装完成&#xff0c;下面是设置的过程关键总结。 一、Devices Android设备(Device)选择 二、Kits &#xf…

网络安全-XSS的原理、攻击及防御

简介 跨站脚本攻击(全称Cross Site Scripting,为和CSS&#xff08;层叠样式表&#xff09;区分&#xff0c;简称为XSS)是指恶意攻击者在Web页面中插入恶意javascript代码&#xff08;也可能包含html代码&#xff09;&#xff0c;当用户浏览网页之时&#xff0c;嵌入其中Web里面…

【C++开发】Qt+Tesseract实现文字识别的各种坑(已解决)

文章目录 Tesseract库下载Qt版本选择安装步骤 VS2017安装MSVC调试器安装构建套件的导入文字识别功能的检测 最近在给之前Qt医疗管理系统项目添加一个文字识别功能&#xff0c;但是在其中遇到非常多坑&#xff0c;花费了我比较多的时间&#xff08;查阅了很多文章&#xff09;&a…

基础学习——关于list、numpy、torch在float和int等数据类型转换方面的总结

系列文章目录 Numpy学习——创建数组及常规操作&#xff08;数组创建、切片、维度变换、索引、筛选、判断、广播&#xff09; Tensor学习——创建张量及常规操作&#xff08;创建、切片、索引、转换、维度变换、拼接&#xff09; 基础学习——numpy与tensor张量的转换 基础学习…

【软件测试】一个完整的项目流程是什么样的?

软件测试是使用人工或者自动的手段来运行或者测定某个软件系统的过程&#xff0c;其目的在于检验它是否满足规定的需求或弄清预期结果与实际结果之间的差别。 在软件投入使用前&#xff0c;要经过一系列的严格测试&#xff0c;才能保证交付质量。 一、引言 1.编写目的 本文档…

2023年度第四届全国大学生算法设计与编程挑战赛(春季赛)

目录 2023年度第四届全国大学生算法设计与编程挑战赛&#xff08;春季赛&#xff09;1、A2、Bx3、Cut4、Diff5、EchoN6、Farmer7、GcdGame8、HouseSub9、IMissYou!10、Jargonless 2023年度第四届全国大学生算法设计与编程挑战赛&#xff08;春季赛&#xff09; 1、A 题目描述…