概率DP求期望

news2024/12/28 3:37:19

[NOIP2016 提高组] 换教室

链接:https://www.luogu.com.cn/problem/P1850

题目描述

对于刚上大学的牛牛来说,他面临的第一个问题是如何根据实际情况申请合适的课程。

在可以选择的课程中,有 2 n 2n 2n 节课程安排在 n n n 个时间段上。在第 i i i 1 ≤ i ≤ n 1 \leq i \leq n 1in)个时间段上,两节内容相同的课程同时在不同的地点进行,其中,牛牛预先被安排在教室 c i c_i ci 上课,而另一节课程在教室 d i d_i di 进行。

在不提交任何申请的情况下,学生们需要按时间段的顺序依次完成所有的 n n n 节安排好的课程。如果学生想更换第 i i i 节课程的教室,则需要提出申请。若申请通过,学生就可以在第 i i i 个时间段去教室 d i d_i di 上课,否则仍然在教室 c i c_i ci 上课。

由于更换教室的需求太多,申请不一定能获得通过。通过计算,牛牛发现申请更换第 i i i 节课程的教室时,申请被通过的概率是一个已知的实数 k i k_i ki,并且对于不同课程的申请,被通过的概率是互相独立的。

学校规定,所有的申请只能在学期开始前一次性提交,并且每个人只能选择至多 m m m 节课程进行申请。这意味着牛牛必须一次性决定是否申请更换每节课的教室,而不能根据某些课程的申请结果来决定其他课程是否申请;牛牛可以申请自己最希望更换教室的 m m m 门课程,也可以不用完这 m m m 个申请的机会,甚至可以一门课程都不申请。

因为不同的课程可能会被安排在不同的教室进行,所以牛牛需要利用课间时间从一间教室赶到另一间教室。

牛牛所在的大学有 v v v 个教室,有 e e e 条道路。每条道路连接两间教室,并且是可以双向通行的。由于道路的长度和拥堵程度不同,通过不同的道路耗费的体力可能会有所不同。 当第 i i i 1 ≤ i ≤ n − 1 1 \leq i \leq n-1 1in1)节课结束后,牛牛就会从这节课的教室出发,选择一条耗费体力最少的路径前往下一节课的教室。

现在牛牛想知道,申请哪几门课程可以使他因在教室间移动耗费的体力值的总和的期望值最小,请你帮他求出这个最小值。

输入格式

第一行四个整数 n , m , v , e n,m,v,e n,m,v,e n n n 表示这个学期内的时间段的数量; m m m 表示牛牛最多可以申请更换多少节课程的教室; v v v 表示牛牛学校里教室的数量; e e e表示牛牛的学校里道路的数量。

第二行 n n n 个正整数,第 i i i 1 ≤ i ≤ n 1 \leq i \leq n 1in)个正整数表示 c i c_i ci,即第 i i i 个时间段牛牛被安排上课的教室;保证 1 ≤ c i ≤ v 1 \le c_i \le v 1civ

第三行 n n n 个正整数,第 i i i 1 ≤ i ≤ n 1 \leq i \leq n 1in)个正整数表示 d i d_i di,即第 i i i 个时间段另一间上同样课程的教室;保证 1 ≤ d i ≤ v 1 \le d_i \le v 1div

第四行 n n n 个实数,第 i i i 1 ≤ i ≤ n 1 \leq i \leq n 1in)个实数表示 k i k_i ki,即牛牛申请在第 i i i 个时间段更换教室获得通过的概率。保证 0 ≤ k i ≤ 1 0 \le k_i \le 1 0ki1

接下来 e e e 行,每行三个正整数 a j , b j , w j a_j, b_j, w_j aj,bj,wj,表示有一条双向道路连接教室 a j , b j a_j, b_j aj,bj,通过这条道路需要耗费的体力值是 w j w_j wj;保证 1 ≤ a j , b j ≤ v 1 \le a_j, b_j \le v 1aj,bjv 1 ≤ w j ≤ 100 1 \le w_j \le 100 1wj100

保证 1 ≤ n ≤ 2000 1 \leq n \leq 2000 1n2000 0 ≤ m ≤ 2000 0 \leq m \leq 2000 0m2000 1 ≤ v ≤ 300 1 \leq v \leq 300 1v300 0 ≤ e ≤ 90000 0 \leq e \leq 90000 0e90000

保证通过学校里的道路,从任何一间教室出发,都能到达其他所有的教室。

保证输入的实数最多包含 3 3 3 位小数。

输出格式

输出一行,包含一个实数,四舍五入精确到小数点后恰好 2 2 2位,表示答案。你的输出必须和标准输出完全一样才算正确。

测试数据保证四舍五入后的答案和准确答案的差的绝对值不大于 4 × 1 0 − 3 4 \times 10^{-3} 4×103。 (如果你不知道什么是浮点误差,这段话可以理解为:对于大多数的算法,你可以正常地使用浮点数类型而不用对它进行特殊的处理)

样例 #1

样例输入 #1

3 2 3 3
2 1 2
1 2 1
0.8 0.2 0.5 
1 2 5
1 3 3
2 3 1

样例输出 #1

2.80

提示

【样例1说明】

所有可行的申请方案和期望收益如下表:

【提示】

  1. 道路中可能会有多条双向道路连接相同的两间教室。 也有可能有道路两端连接的是同一间教室。
  2. 请注意区分n,m,v,e的意义, n不是教室的数量, m不是道路的数量。

特殊性质1:图上任意两点 a i a_i ai, b i b_i bi, a i a_i ai b i b_i bi间,存在一条耗费体力最少的路径只包含一条道路。

特殊性质2:对于所有的 1 ≤ i ≤ n 1≤ i≤ n 1in k i = 1 k_i= 1 ki=1

思路

概率dp求期望:

状态表示:f[i][j][0/1]表示当前为第i个时段,已经用了j次换教室的机会,这次换/不换的路径总和的最小期望

初始化:f[1][0][0]=f[1][1][1]=0,其他正无

答案为:min(f[n][i][0/1]), i ∈ [ 0 , m ] i \in [0,m] i[0,m]

状态转移:

  • 上次不换,这次不换:f[i - 1][j][0] + dist[c[i - 1]][c[i]];
  • 上次换,这次不换:f[i - 1][j][1] + dist[c[i - 1]][c[i]] * (1 - p[i - 1]) + dist[d[i - 1]][c[i]] * p[i - 1];
  • 上次不换,这次换:f[i - 1][j - 1][0] + dist[c[i - 1]][c[i]] * (1 - p[i]) + dist[c[i - 1]][d[i]] * p[i];
  • 上次换,这次换:
    • 分上次成功,这次成功,
    • 上次成功,这次失败
    • 上次失败,这次成功,
    • 上次失败,这次失败
double t4 = f[i - 1][j - 1][1];
t4 += dist[c[i - 1]][c[i]] * (1 - p[i - 1]) * (1 - p[i]);
t4 += dist[c[i - 1]][d[i]] * (1 - p[i - 1]) * p[i];
t4 += dist[d[i - 1]][c[i]] * p[i - 1] * (1 - p[i]);
t4 += dist[d[i - 1]][d[i]] * p[i - 1] * p[i];

教室与教室之间的路径可以使用floyd算法求解。

代码

#include <bits/stdc++.h>

#define int long long
using namespace std;

const int N = 2010;
int n, m, v, e;
int c[N], d[N];
double p[N], f[N][N][2], dist[N][N];

signed main() {
#ifndef ONLINE_JUDGE
    freopen("test.in", "r", stdin);
    freopen("test.out", "w", stdout);
#endif
    cin >> n >> m >> v >> e;
    for (int i = 1; i <= n; i++) cin >> c[i];
    for (int i = 1; i <= n; i++) cin >> d[i];
    for (int i = 1; i <= n; i++) cin >> p[i];

    for (int i = 1; i <= v; i++) {
        for (int j = 1; j <= v; j++) {
            if (i != j) dist[i][j] = 1e18;
        }
    }

    for (int i = 1; i <= e; i++) {
        int x, y, w;
        cin >> x >> y >> w;
        dist[x][y] = dist[y][x] = min(dist[x][y], 1.0 * w);
    }

    for (int k = 1; k <= v; k++) {
        for (int i = 1; i <= v; i++) {
            for (int j = 1; j <= v; j++) {
                dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
            }
        }
    }

    for (int i = 1; i <= n; i++) {
        for (int j = 0; j <= m; j++) {
            f[i][j][0] = f[i][j][1] = 1e18;
        }
    }
    f[1][0][0] = f[1][1][1] = 0;


    for (int i = 2; i <= n; i++) {
        for (int j = 0; j <= min(i, m); j++) {
            //上次不换,这次不换
            double t1 = f[i - 1][j][0] + dist[c[i - 1]][c[i]];
            //上次换,这次不换
            double t2 = f[i - 1][j][1] + dist[c[i - 1]][c[i]] * (1 - p[i - 1]) + dist[d[i - 1]][c[i]] * p[i - 1];
            f[i][j][0] = min(t1, t2);
            //上次不换,这次换
            if (j == 0) continue;
            double t3 = f[i - 1][j - 1][0] + dist[c[i - 1]][c[i]] * (1 - p[i]) + dist[c[i - 1]][d[i]] * p[i];
            //上次换,这次换
            double t4 = f[i - 1][j - 1][1];
            t4 += dist[c[i - 1]][c[i]] * (1 - p[i - 1]) * (1 - p[i]);
            t4 += dist[c[i - 1]][d[i]] * (1 - p[i - 1]) * p[i];
            t4 += dist[d[i - 1]][c[i]] * p[i - 1] * (1 - p[i]);
            t4 += dist[d[i - 1]][d[i]] * p[i - 1] * p[i];
            f[i][j][1] = min(t3, t4);
        }
    }
    double res = 1e18;
    for (int j = 0; j <= m; j++) {
        res = min(res, min(f[n][j][0], f[n][j][1]));
    }
    std::printf("%.2f", res);


    return 0;
}

绿豆蛙的归宿

题目背景

随着新版百度空间的上线,Blog 宠物绿豆蛙完成了它的使命,去寻找它新的归宿。

题目描述

给出张 n n n 个点 m m m 条边的有向无环图,起点为 1 1 1,终点为 n n n,每条边都有一个长度,并且从起点出发能够到达所有的点,所有的点也都能够到达终点。

绿豆蛙从起点出发,走向终点。 到达每一个顶点时,如果该节点有 k k k 条出边,绿豆蛙可以选择任意一条边离开该点,并且走向每条边的概率为 1 k \frac{1}{k} k1 。现在绿豆蛙想知道,从起点走到终点的所经过的路径总长度期望是多少?

输入格式

输入的第一行是两个整数,分别代表图的点数 n n n 和边数 m m m

2 2 2 到第 ( m + 1 ) (m + 1) (m+1) 行,每行有三个整数 u , v , w u, v, w u,v,w,代表存在一条从 u u u 指向 v v v 长度为 w w w 的有向边。

输出格式

输出一行一个实数代表答案,四舍五入保留两位小数。

样例 #1

样例输入 #1

4 4 
1 2 1 
1 3 2 
2 3 3 
3 4 4

样例输出 #1

7.00

提示

数据规模与约定

  • 对于 20 % 20\% 20% 的数据,保证 n ≤ 1 0 2 n \leq 10^2 n102
  • 对于 40 % 40\% 40% 的数据,保证 n ≤ 1 0 3 n \leq 10^3 n103
  • 对于 60 % 60\% 60% 的数据,保证 n ≤ 1 0 4 n \leq 10^4 n104
  • 对于 100 % 100\% 100% 的数据,保证 1 ≤ n ≤ 1 0 5 1 \leq n \leq 10^5 1n105 1 ≤ m ≤ 2 × n 1 \leq m \leq 2 \times n 1m2×n 1 ≤ u , v ≤ n 1 \leq u, v \leq n 1u,vn 1 ≤ w ≤ 1 0 9 1 \leq w \leq 10^9 1w109,给出的图无重边和自环。

思路

记忆化搜索

f[i]表示从i走到终点n的路径总长的期望

起点:f[n]=0

终点:f[1]

转移:f[x]+=(f[y]+w)*d[x]

image-20230703194116084

代码

#include <bits/stdc++.h>

#define int long long
using namespace std;

const int N = 1e5 + 10;
int n, m;
vector<pair<int, int>> e[N];
vector<int> d(N);
vector<double> f(N);//从i走到u的期望

double dfs(int x) {
    if (f[x]) return f[x];
    for (auto [y, w]: e[x]) {
        f[y] = dfs(y);
        f[x] += (f[y] + w) * 1.0 / d[x];
    }
    return f[x];
}


signed main() {
#ifndef ONLINE_JUDGE
    freopen("test.in", "r", stdin);
    freopen("test.out", "w", stdout);
#endif
    cin >> n >> m;
    for (int i = 1; i <= m; i++) {
        int a, b, c;
        cin >> a >> b >> c;
        e[a].emplace_back(b, c);
        d[a]++;
    }
    dfs(1);
    std::printf("%.2f", f[1]);
    return 0;
}

拓扑排序

需要反向建图

image-20230703195744673

代码

#include <bits/stdc++.h>

#define int long long
using namespace std;

const int N = 1e5 + 10;
typedef pair<int, int> PII;
vector<PII> e[N];
int n, m;
vector<int> d(N), k(N);
vector<double> f(N);

void topsort() {
    queue<int> q;
    q.push(n);
    while (q.size()) {
        auto x = q.front();
        q.pop();
        for (auto [y, w]: e[x]) {
            f[y] += (f[x] + w) * 1 / k[y];
            if (--d[y] == 0)q.push(y);
        }
    }
}

signed main() {
#ifndef ONLINE_JUDGE
    freopen("test.in", "r", stdin);
    freopen("test.out", "w", stdout);
#endif
    cin >> n >> m;
    for (int i = 1; i <= m; i++) {
        int a, b, c;
        cin >> a >> b >> c;
        e[b].push_back({a, c});
        d[a]++, k[a]++;
    }
    topsort();
    std::printf("%.2f", f[1]);


    return 0;
}

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

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

相关文章

D352周赛复盘:重点是双指针滑动窗口+质数判断

文章目录 6909.最长奇偶子数组&#xff08;双指针&#xff09;思路完整版 6916.和等于目标的质数对&#xff08;质数判断&#xff0c;重要&#xff09;思路质数判断&#xff1a;埃拉托斯特尼筛法获取所有小于等于n的质数质数定义 完整版为什么只遍历到n/2&#xff1f; 时间复杂…

python 深度学习 解决遇到的报错问题2

目录 一、解决报错UnicodeDecodeError: utf-8 codec cant decode byte 0xe3 in position 15: invalid continuation byte 二、解决ERROR: Could not build wheels for pycocotools, which is required to install pyproject.toml-based pro 三、解决OSError: [WinError 1314…

flutter 中实现动态表单 form generator

flutter 中实现动态表单 form generator 前言 最近有人问我 flutter 前端如何处理动态表单。 这种是企业开发中的常见问题&#xff0c;特别是问卷和工作流审核表单。 今天我们就来实现下这个功能&#xff0c;主要是处理这个业务功能的思路。 原文 https://ducafecat.com/blog/…

通用分页(下)

一.理解分页思想 1.分页的实质 1.1&#xff08;自我概述&#xff09; 用最简单的话来说&#xff0c;就是在一个界面展示不了那么多数据时&#xff0c;通过一点手段将数据一部分一部分的加载出来&#xff0c;从而减少服务器的压力。并且使能够让服务器利用率提高&#xff01; …

把yum源配置为ftp服务

配置yum源为ftp服务 一、在node1部署ftp服务器1.1 挂载镜像1.2 配置ftp的根目录 二、配置node2的yum源为node1的ftp服务器2.1 移除node2中默认的yum源文件2.2 创建新的yum源文件2.3 更新yum软件列表 环境介绍&#xff1a;有node1和node2两台Centos7虚拟机 环境准备&#xff1a;…

C++ 图的遍历

1. 图的遍历 给定一个图 G 和其中任意一个顶点 v0 &#xff0c;从 v0 出发&#xff0c;沿着图中各边访问图中的所有顶点&#xff0c;且每个顶 点仅被遍历一次 。 " 遍历 " 即对结点进行某种操作的意思 。 请思考树以前是怎么遍历的&#xff0c;此处可以直接用来遍…

手搓GPT系列之 - 通过理解LSTM的反向传播过程,理解LSTM解决梯度消失的原理 - 逐条解释LSTM创始论文全部推导公式,配超多图帮助理解(下篇)

本文承接上篇上篇在此和中篇中篇在此&#xff0c;继续就Sepp Hochreiter 1997年的开山大作 Long Short-term Memory 中APPENDIX A.1和A.2所载的数学推导过程进行详细解读。希望可以帮助大家理解了这个推导过程&#xff0c;进而能顺利理解为什么那几个门的设置可以解决RNN里的梯…

Spring中@NotEmpty、@NotBlank、@NotNull 的区别和使用

1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>2.0.5.RELEASE</version> </dependency>NotEmpty、NotBlank、NotNull 包的位置&#xff1…

i春秋,春秋云镜系列

目录 先提神CVE-2022-32991靶标介绍&#xff1a;复现&#xff1a; CVE-2022-30887靶标介绍&#xff1a;复现 先提神 CVE-2022-32991 靶标介绍&#xff1a; 该CMS的welcome.php中存在SQL注入攻击。 复现&#xff1a; 打开靶场地址&#xff0c;三个随便选一个进去&#xff0c…

Gof23设计模式之适配器模式

1.定义 将一个类的接口转换成客户希望的另外一个接口&#xff0c;使得原本由于接口不兼容而不能一起工作的那些类能一起工作。 适配器模式分为类适配器模式和对象适配器模式&#xff0c;前者类之间的耦合度比后者高&#xff0c;且要求程序员了解现有组件库中的相关组件的内部结…

国产划片机开创了半导体芯片切割的新工艺时代

国产划片机确实开创了半导体芯片切割的新工艺时代。划片机是一种用于切割和划分半导体芯片的设备&#xff0c;它是半导体制造过程中非常重要的一环。在过去&#xff0c;划片机技术一直被国外厂商所垄断&#xff0c;国内半导体制造企业不得不依赖进口设备。 然而&#xff0c;随着…

QT学习笔记6--信号之间的连接

连接 仍然使用connect函数&#xff0c;但是和函数重载类似&#xff0c;需要用到函数指针。如下所示 void (teacher:: *teachersignals)(void) &teacher::hungery;void (student:: *studentslots)(void) &student::treat;connect(zt,teachersignals,st,studentslots)…

水利三类人员专职安全生产管理人员c证安全生产法律法规考试题库

​本题库是根据最新考试大纲要求&#xff0c;结合近年来考试真题的重难点进行汇编整理组成的全真模拟试题&#xff0c;考生们可以进行专项训练&#xff0c;查漏补缺巩固知识点。本题库对热点考题和重难点题目都进行了仔细的整理和编辑&#xff0c;相信考生在经过了针对性的刷题…

浏览器使用Notification桌面通知消息推送

什么是 Notification&#xff1f; Notification 是浏览器最小化后在桌面显示消息的一种方法类似于 360 等流氓软件在桌面右下角的弹窗广告它与浏览器是脱离的&#xff0c;消息是置顶的 一、弹窗授权 授权当前页面允许通知可以通过检查只读属性 Notification.permission 的值来…

基于Springboot+Html的健身房管理系统

✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取项目下载方式&#x1f345; 一、项目背景介绍&#xff1a; 随着现代生活方式的改…

基于改进莱维飞行和混沌映射的金鹰优化算法(10种混沌映射随意切换),附matlab代码

“ 本篇文章对金鹰优化算法进行改进&#xff0c;首先通过引入混沌映射机制&#xff0c;对其群体进行初始化&#xff0c;增加金鹰个体的多样性&#xff1b;然后在金鹰个体的位置更新公式上引入改进的莱维飞行机制&#xff0c;提高搜索精度&#xff0c;帮助金鹰个体跳出局部最优。…

谈谈NLP中 大语言模型LLM的 思维链 Chain-of-Thought(CoT)

Chain-of-Thought(CoT) 1.介绍 在过去几年的探索中&#xff0c;业界发现了一个现象&#xff0c;在增大模型参数量和训练数据的同时&#xff0c;在多数任务上&#xff0c;模型的表现会越来越好。因而&#xff0c;现有的大模型LLM&#xff0c;最大参数量已经超过了千亿。 然而…

大数据Doris(五十五):BACKUP数据备份案例和注意事项

文章目录 BACKUP数据备份案例和注意事项 一、BACKUP数据备份案例 1、Doris中创建数据库&#xff0c;以及建表插入数据 2、创建远端仓库 3、全量备份指定 Doris 库下所有表所有分区数据 4、查看 backup 作业执行情况 5、查看远端仓库中已备份结果 二、注意事项 BACKUP数…

【花雕】青少年机器人技术等级考试理论综合试卷(一级)2021年9月

随着科技的不断进步&#xff0c;机器人技术已经成为了一个重要的领域。在这个领域中&#xff0c;机械结构是机器人设计中至关重要的一部分&#xff0c;它决定了机器人的形态、运动方式和工作效率。对于青少年机器人爱好者来说&#xff0c;了解机械结构的基础知识&#xff0c;掌…

Drools用户手册翻译——第二章 入门(下)测试和评估

因为篇幅原因&#xff0c;所以分为上下两个部分&#xff0c;主要就是通过一个交通违章项目的例子&#xff0c;带你先粗略感受一下决策模型的使用流程&#xff0c;总体来说有详细&#xff0c;也有没说清的地方&#xff0c;如果想要了解一下决策模型&#xff0c;可以进来了解一下…