news 2026/5/5 18:47:56

《P1850 [NOIP 2016 提高组] 换教室》

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
《P1850 [NOIP 2016 提高组] 换教室》

题目背景

NOIP2016 提高组 D1T3

题目描述

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

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

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

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

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

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

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

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

输入格式

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

第二行 n 个正整数,第 i(1≤i≤n)个正整数表示 ci​,即第 i 个时间段牛牛被安排上课的教室;保证 1≤ci​≤v。

第三行 n 个正整数,第 i(1≤i≤n)个正整数表示 di​,即第 i 个时间段另一间上同样课程的教室;保证 1≤di​≤v。

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

接下来 e 行,每行三个正整数 aj​,bj​,wj​,表示有一条双向道路连接教室 aj​,bj​,通过这条道路需要耗费的体力值是 wj​;保证 1≤aj​,bj​≤v,1≤wj​≤100。

保证 1≤n≤2000,0≤m≤2000,1≤v≤300,0≤e≤90000。

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

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

输出格式

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

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

输入输出样例

输入 #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 说明

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

  • 不作申请,耗费的体力值的期望为 8.0。
申请通过的时间段出现的概率耗费的体力值
1.08
  • 申请更换第 1 个时间段的上课教室,耗费的体力值的期望为 4.8。
申请通过的时间段出现的概率耗费的体力值
10.84
0.28
  • 申请更换第 2 个时间段的上课教室,耗费的体力值的期望为 6.4。
申请通过的时间段出现的概率耗费的体力值
20.20
0.88
  • 申请更换第 3 个时间段的上课教室,耗费的体力值的期望为 6.0。
申请通过的时间段出现的概率耗费的体力值
30.54
0.58
  • 申请更换第 1,2 个时间段的上课教室,耗费的体力值的期望为 4.48。
申请通过的时间段出现的概率耗费的体力值
1,20.164
10.644
20.040
0.168
  • 申请更换第 1,3 个时间段的上课教室,耗费的体力值的期望为 2.8。
申请通过的时间段出现的概率耗费的体力值
1,30.40
10.44
30.14
0.18
  • 申请更换第 2,3 个时间段的上课教室,耗费的体力值的期望为 5.2。
申请通过的时间段出现的概率耗费的体力值
2,30.14
20.10
30.44
0.48

因此,最优方案为:申请更换第 1,3 个时间段的上课教室。耗费的体力值的期望为 2.8。

提示

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

数据范围与说明

测试点编号n≤m≤v≤是否具有特殊性质 1是否具有特殊性质 2
111300××
22020××
321100××
422300××
53020
631100×
732300××
8100300
910120×
10102100××
111010300×
1220020×
13201100××
14202300×
152020300×
16300020××
173001100××
183002300
19300300300×
202000020××
212000120××
2220002100××
2320002000100××
2420002000300××
2520002000300××

特殊性质 1:图上任意不同的两点 u,v 间,存在一条耗费体力最少的路径只包含一条道路。

特殊性质 2:对于所有的 1≤i≤n, ki​=1。

代码实现:

#include<cstdio> #include<algorithm> using namespace std; double p[2005], dis[305][305]; double dp[2005][2005][2]; int u[2005], v[2005]; int main() { int n, m, cnt, e; scanf("%d%d%d%d",&n,&m,&cnt,&e); for(int i=1;i<=n;i++) { scanf("%d",&u[i]); } for(int i=1;i<=n;i++) { scanf("%d",&v[i]); } for(int i=1;i<=n;i++) { scanf("%lf",&p[i]); } for(int i=1;i<=301;i++) { for(int j=1;j<=301;j++) { dis[i][j]=1000000000; } } for(int i=1;i<=300;i++) dis[i][i]=0; for(int i=1;i<=e;i++) { int x,y; double z; scanf("%d%d%lf",&x,&y,&z); dis[x][y]=dis[y][x]=min(dis[x][y],z); } for(int kk=1;kk<=cnt;kk++) { for(int i=1;i<=cnt;i++) { for(int j=1;j<=cnt;j++) { dis[i][j]=min(dis[i][j],dis[i][kk]+dis[kk][j]); } } } for(int i=1;i<=n;i++) { for(int j=0;j<=m;j++) { dp[i][j][0]=dp[i][j][1]=1000000000; } } dp[1][0][0]=dp[1][1][1]=0; for(int i=2;i<=n;i++) { for(int j=0;j<=min(i,m);j++) { dp[i][j][0]=min(dp[i][j][0],dp[i-1][j][0]+dis[u[i-1]][u[i]]); dp[i][j][0]=min(dp[i][j][0],dp[i-1][j][1]+(1-p[i-1])*dis[u[i-1]][u[i]]+p[i-1]*dis[v[i-1]][u[i]]); if(j) { dp[i][j][1]=min(dp[i][j][1],dp[i-1][j-1][0]+p[i]*dis[u[i-1]][v[i]]+(1-p[i])*dis[u[i-1]][u[i]]); dp[i][j][1]=min(dp[i][j][1],dp[i-1][j-1][1]+p[i-1]*p[i]*dis[v[i-1]][v[i]]+p[i-1]*(1-p[i])*dis[v[i-1]][u[i]]+(1-p[i-1])*p[i]*dis[u[i-1]][v[i]]+(1-p[i-1])*(1-p[i])*dis[u[i-1]][u[i]]); } } } double res=1000000000; for(int i=0;i<=m;i++) { res=min(res,dp[n][i][1]); res=min(res,dp[n][i][0]); } printf("%.2lf\n",res); return 0; }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/5 9:27:22

我让AI读了1000个GitHub测试项目,总结出“最佳实践”

‌一、测试工程的四大支柱‌基于对1000 GitHub 测试项目、科技巨头公开文档及行业实践的深度分析&#xff0c;软件测试的最佳实践已形成清晰的四维框架&#xff1a;维度核心实践代表项目/工具关键价值‌测试架构‌测试金字塔&#xff08;80%单元 15%集成 5%E2E&#xff09;Go…

作者头像 李华
网站建设 2026/5/3 2:48:44

为什么AI生成的测试用例比人工更“刁钻”?

重新定义“刁钻”测试用例 在软件测试领域&#xff0c;“刁钻”测试用例特指那些能有效暴露隐藏缺陷、覆盖边缘场景的用例&#xff0c;它们往往超出常规逻辑&#xff0c;挑战系统极限。传统人工测试依赖于测试工程师的经验和直觉&#xff0c;但受限于认知偏差和时间压力&#…

作者头像 李华
网站建设 2026/5/4 2:18:43

计算机视觉与机器学习在语音交互中的应用

Alexa & Friends 特邀 Pradeep Natarajan&#xff0c;Alexa AI 首席应用科学家 2021年10月28日&#xff0c;某中心 Alexa AI 团队的首席应用科学家 Pradeep Natarajan 加入了首席 Alexa 技术推广专家 Jeff Blankenburg 的播客节目《Alexa & Friends》&#xff0c;讨论了…

作者头像 李华
网站建设 2026/4/28 10:29:55

Spring Boot 中使用 JSONPath 高效处理 JSON 数据

前言在日常开发中&#xff0c;我们经常需要处理 JSON 数据&#xff0c;特别是从复杂的 JSON 结构中提取特定字段。传统的处理方式如 Gson、Jackson 的 API 虽然功能强大&#xff0c;但在处理复杂路径提取时代码往往显得冗长且不易维护。今天给大家介绍一个更优雅的解决方案 ——…

作者头像 李华
网站建设 2026/4/30 7:36:56

MySQL自增id超过int最大值的场景

点击标题下「蓝色微信名」可快速关注 数据库的主键我们有时候会用自增列&#xff0c;但是自增都会有个上限&#xff0c;如果达到怎么办&#xff1f;技术社群的这篇文章《MySQL自增id超过int最大值怎么办&#xff1f;》就给我们讲解了MySQL数据库自增列达到上限该怎么办&#xf…

作者头像 李华
网站建设 2026/4/28 17:13:38

ssm651网上鲜花店网站vue

目录网上鲜花店网站&#xff08;Vue框架&#xff09;摘要开发技术源码文档获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01;网上鲜花店网站&#xff08;Vue框架&#xff09;摘要 该鲜花店网站基于Vue.js框架开发&#xff0c;结合Spring、SpringM…

作者头像 李华