做完这道题才略微感觉自己懂了一点关于概率与期望的知识QAQ。。。

一:关于概率与期望的定义

转载节选于blog

1、什么是数学期望?

数学期望亦称期望、期望值等。在概率论和统计学中,一个离散型随机变量的期望值是试验中每一次可能出现的结果的概率乘以其结果的总和。

这是什么意思呢?假如我们来玩一个游戏,一共52张牌,其中有4个A。我们1元钱赌一把,如果你抽中了A,那么我给你10元钱,否则你的1元钱就输给我了。在这个游戏中,抽中的概率是113(452)

,结果是赢10元钱;抽不中概率是1213,结果是亏1元钱。那么你赢的概率,也就是期望值是−213。这样,你玩了很多把之后,一算账,发现平均每把会亏−213

元。

一般在竞赛中,若X是一个离散型的随机变量,可能值为x1,x2

……,对应概率为p1,p2……,概率和为1,那么期望值E(X)=∑ipixi

对于数学期望,我们还应该明确一些知识点:

(1)期望的“线性”性质。对于所有满足条件的离散型的随机变量X,Y和常量a,b,有:E(aX+bY)=aE(x)+bE(y)

类似的,我们还有E(XY)=E(X)+E(Y)

(2)全概率公式 假设{Bn∣n=1,2,3,...

}是一个“概率空间有限或可数无限”的分割,且集合Bn

是一个“可数集合”,则对于任意事件A有:

P(A)=∑nP(A∣Bn)P(Bn)

(3)全期望公式 E(Y)=E(E(Y∣X))=∑iP(X=xi)E(Y∣X=xi)

2、数学期望怎么用?

确实,数学期望在数学的范围里是一个较为复杂,但是却十分有用的一个部分。

但是题型类型多,花样也多,有时无从下手。明知是数学期望,却找不到正确的算法解决问题。

于是,我们来分析一下:

(1)对于很大一部分的期望问题,递推是个好帮手。我们一般在草稿纸上,把题目中隐含的期望值之间的关系,然后经过计算等方法,找出一个递推式。这个递推式,不要求我们枚举每一种可能(不然就没有用递推的意义了),而是根据一些已有的,或是可以直接简单地推算出的期望值,算出其他状态下的期望。这个道理道理大家也都明白,可是有时是很难找到递推式的。这时,我们就应该用我们之前讲过的期望的定义——E(X)=∑ipixi

,然后再结合期望的“线性”性质和全概率、全期望公式,一步步地像“剥笋皮”一样,找到问题的核心,这样效果往往很好。

(2)另外,有决策、满足最优子结构的期望问题,我们还可以考虑人们常常与“递推”弄混的“动态规划”。这里,我们一般用期望表示状态,期望的正负高低,就能决定这个状态的优和劣。

(3)对于上述两种方法都不能解决的,这也算是比较少了。这时,常见的尝试方法之一就是高斯消元法。我们可以先尝试建立一个线性方程组,然后进行高斯消元等操作

其实以上的理论我看着也。。。。

也给大家推荐一个blog,里面有许多的关于这个专题的详解和例题。

二:关于此题。。。

1、题目大意:

有一个v个节点的无向图,共有e条边,牛牛应该上n节课,第i课同时在c[i]与d[i]进行,牛牛都可以去上,唯一的区别是在c[i]上课不需要申请而在d[i]则需要,并且仅有m次机会申请,通过概率为p[i];要求的就是牛牛移动的体力值总和的期望值最小。

2、大概思路

(1)初始化

首先就是对于这v个点之间的最短路径进行处理,因为仅仅有300个点,所以即使用Floyd也不会爆掉,但是感人感觉用v遍优先队列优化的Dij会更稳一些,这里给出代码

void dij(int x)
{
memset(vis,false,sizeof(vis));
for(int i=1;i<=v;i++)
dis[x][i]=INF;
q.push(mp(0,x));
dis[x][x]=0;
while(!q.empty())
{
int y=q.top().second;
q.pop();
if(vis[y]) continue;
vis[y]=true;
for(int i=head[y];i;i=nxt[i])
if(dis[x][ver[i]]>dis[x][y]+eage[i])
{
dis[x][ver[i]]=dis[x][y]+eage[i];
q.push(mp(-dis[x][ver[i]],ver[i]));
}
}
}

对于路径储存,有兴趣的可以学一下vector+pair储存blog

其次便是对于dp数组f的初始化了

f[i][j][k]表示在前i节课,申请j次,且用k表示第i次有无申请;一定要注意这个地方k表示的不是是否申请成功而是有无申请,在这个地方卡了好久orz。

因为要求最小值所以把f都赋值成极大值

f[1][0][0]与f[1][1][1]以为是初始位置所以都是0。

此外还要注意在第i次的时候要先处理一下j=0的情况

即f[i][0][0]=f[i-1][0][0]+dis[c[i-1]][c[i]];

牛牛从未申请过所以直接拿f[i-1][0][0]加c[i-1]与c[i]的距离就可以了。

(2)算法主体

f[i][j][0]就可以等于以下两种的较小值

  1. 上一次未申请的f[i-1][j][0]加上c[i]与c[i-1]的距离;
  2. 上一次申请的f[i-1][j][1]有p[i-1]的概率申请成功,有(1-p[i-1])的概率申请失败,所以应该为f[i-1][j][1]与p[i-1]dis[c[i]][d[i-1]]+(1-p[i-1])dis[c[i]][c[i-1]]的和。

同样的f[i][j][1]也有p[i]的概率成功,就可以等于以下两种的较小值

  1. 上一次未申请的f[i-1][j-1][0]+p[i]dis[c[i-1]][d[i]]+(1-p[i])dis[c[i-1]][c[i]];
  2. 上一次申请的f[i-1][j-1][1]+p[i](p[i-1]dis[d[i-1]][d[i]]+(1-p[i-1])dis[c[i-1]][d[i]])+(1-p[i])(p[i-1]dis[d[i-1]][c[i]]+(1-p[i-1])dis[c[i-1]][c[i]]。

(3)输出

求出前n个中申请1-m次的最小值

for(int i=0;i<=m;i++)
ans=min(ans,min(f[n][i][0],f[n][i][1]));
printf("%.2lf",ans);

3、CODE

#include<bits/stdc++.h>
#define ll long long
#define pb push_back
#define mp make_pair
using namespace std;
const int N=9e4;
const int INF=1e9;
int n,m,v,e,tot,head[2*N+5],nxt[2*N+5],eage[2*N+5],ver[2*N+5],c[2005],d[2005];
double p[2005],f[2005][2005][2],dis[2005][2005],ans=INF;
bool vis[2005];
priority_queue<pair<int,int> > q;
void add(int x,int y,int t)
{
ver[++tot]=y,eage[tot]=t;
nxt[tot]=head[x],head[x]=tot;
}
void dij(int x)
{
memset(vis,false,sizeof(vis));
for(int i=1;i<=v;i++)
dis[x][i]=INF;
q.push(mp(0,x));
dis[x][x]=0;
while(!q.empty())
{
int y=q.top().second;
q.pop();
if(vis[y]) continue;
vis[y]=true;
for(int i=head[y];i;i=nxt[i])
if(dis[x][ver[i]]>dis[x][y]+eage[i])
{
dis[x][ver[i]]=dis[x][y]+eage[i];
q.push(mp(-dis[x][ver[i]],ver[i]));
}
}
}
void init()
{
scanf("%d%d%d%d",&n,&m,&v,&e);
for(int i=1;i<=n;i++)
scanf("%d",&c[i]);
for(int i=1;i<=n;i++)
scanf("%d",&d[i]);
for(int i=1;i<=n;i++)
scanf("%lf",&p[i]);
for(int i=1,x,y,t;i<=e;i++)
{
scanf("%d%d%d",&x,&y,&t);
add(x,y,t);
add(y,x,t);
}
for(int i=0;i<=n;i++)
for(int j=0;j<=m;j++)
f[i][j][0]=f[i][j][1]=INF;
f[1][0][0]=f[1][1][1]=0;
}
int main()
{
init();
for(int i=1;i<=v;i++)
dij(i);
for(int i=2;i<=n;i++)
{
f[i][0][0]=f[i-1][0][0]+dis[c[i-1]][c[i]];
for(int j=1;j<=min(i,m);j++)
{
f[i][j][0]=min(f[i][j][0],min(f[i-1][j][0]+dis[c[i]][c[i-1]],f[i-1][j][1]+p[i-1]*dis[c[i]][d[i-1]]+(1-p[i-1])*dis[c[i]][c[i-1]]));
f[i][j][1]=min(f[i-1][j-1][0]+p[i]*dis[c[i-1]][d[i]]+(1-p[i])*dis[c[i-1]][c[i]],f[i-1][j-1][1]+p[i]*(p[i-1]*dis[d[i-1]][d[i]]+(1-p[i-1])*dis[c[i-1]][d[i]])+(1-p[i])*(p[i-1]*dis[d[i-1]][c[i]]+(1-p[i-1])*dis[c[i-1]][c[i]])); }
}
for(int i=0;i<=m;i++)
ans=min(ans,min(f[n][i][0],f[n][i][1]));
printf("%.2lf",ans);
return 0;
}

题解 P1850 [NOIP2016 提高组] 换教室的更多相关文章

  1. Luogu P1850 [NOIp2016提高组]换教室 | 期望dp

    题目链接 思路: <1>概率与期望期望=情况①的值*情况①的概率+情况②的值*情况②的概率+--+情况n的值*情况n的概率举个例子,抛一个骰子,每一面朝上的概率都是1/6,则这一个骰子落地 ...

  2. [NOIp2016提高组]换教室

    题目大意: 有n节课,第i节课在c[i]上课,同时d[i]也有一节课d[i]. 你有权利向教务处发出m次申请把自己的教室改到d[i],相应的批准概率是k[i]. 教室是图上的一些点,其中每条边都有边权 ...

  3. 洛谷 1850 NOIP2016提高组 换教室

    [题解] 先用floyed处理出两点间的最短路. 设f[i][j][k]表示走到第i个教室,总共换了j次,当前换或者不换,期望的最小移动距离. 分情况讨论来转移即可. #include<cstd ...

  4. 【题解】NOIP2016提高组 复赛

    [题解]NOIP2016提高组 复赛 传送门: 玩具谜题 \(\text{[P1563]}\) 天天爱跑步 \(\text{[P1600]}\) 换教室 \(\text{[P1850]}\) 组合数问 ...

  5. 【题解】NOIP2016 提高组 简要题解

    [题解]NOIP2016 提高组 简要题解 玩具迷题(送分) 用异或实现 //@winlere #include<iostream> #include<cstdio> #inc ...

  6. NOIP2016提高组解题报告

    NOIP2016提高组解题报告 更正:NOIP day1 T2天天爱跑步 解题思路见代码. NOIP2016代码整合

  7. 【题解】NOIP2015提高组 复赛

    [题解]NOIP2015提高组 复赛 传送门: 神奇的幻方 \([P2615]\) 信息传递 \([P2661]\) 斗地主 \([P2668]\) 跳石头 \([P2678]\) 子串 \([P26 ...

  8. 【题解】NOIP2017 提高组 简要题解

    [题解]NOIP2017 提高组 简要题解 小凯的疑惑(数论) 不讲 时间复杂度 大力模拟 奶酪 并查集模板题 宝藏 最优解一定存在一种构造方法是按照深度一步步生成所有的联通性. 枚举一个根,随后设\ ...

  9. [日记&做题记录]-Noip2016提高组复赛 倒数十天

    写这篇博客的时候有点激动 为了让自己不颓 还是写写日记 存存模板 Nov.8 2016 今天早上买了两个蛋挞 吃了一个 然后就做数论(前天晚上还是想放弃数论 但是昨天被数论虐了 woc noip模拟赛 ...

随机推荐

  1. 2021/5/11 docker的应用

    很快一天过去了,今天虽然没有加班,但是依旧感觉疲惫,弄了一天的docker镜像的问题.作为一名前端开发工程师从以前从未听说过docker到现在懂得了如何运用,也是不容易啊.之前也说过,我们项目结构是前 ...

  2. mysql.data.entityframeworkcore 已弃用

    转官网有方案: https://dev.mysql.com/doc/connector-net/en/connector-net-entityframework-core.html General R ...

  3. 封装了一些sqlsugar的常用方法 用来动态切换数据库和依赖注入 支持泛型

    接口: /// <summary> /// 数据库操作 /// </summary> public interface IDAL_Services { /// <summ ...

  4. 利用Typora+PicGo+OSS+Git+Github/码云搭建个人云笔记

    搭建个人云笔记 对于程序员来讲,使用markdown可以帮助我们快速地写作,书写出排版好看,颜值高的笔记,使用markdown来书写文档相比于使用word要简单快捷的多 市面上有很多markdown的 ...

  5. gcc 版本

    $ gcc --versiongcc (Ubuntu 5.4.0-6kord1~16.04.4k2) 5.4.0 20160609Copyright (C) 2015 Free Software Fo ...

  6. 037.Python的UDP语法

    UDP语法 1 创建一个socket的UDP对象 import socket #创建对象 socket.SOCK_DGRAM 代表UDP协议 sk = socket.socket(type=socke ...

  7. systemd 进程管理详解

    systemd进程管理 systemd管理的优势 1.最新系统都采用systemd管理(RedHat7,CentOS7,Ubuntu15...) 2.CentOS7 支持开机并行启动服务,显著提高开机 ...

  8. Redis 哨兵模式配置

    搭建步骤 第一步: 在 redis.conf 配置文件目录下拷贝三份 sentinel.conf 文件 [root@node-01 redis-5.0.9]# cp sentinel.conf sen ...

  9. opencv——PCA(主要成分分析)数学原理推导

    引言: 最近一直在学习主成分分析(PCA),所以想把最近学的一点知识整理一下,如果有不对的还请大家帮忙指正,共同学习. 首先我们知道当数据维度太大时,我们通常需要进行降维处理,降维处理的方式有很多种, ...

  10. iapp后台一本通php源码+iapp源码

    给大家分享一个后台源码,内有后台php源码,还有iapp对接源码,一本通 iapp+ PHP源码 经过一个小时的研究看看,测试了一下, 1.注册登录以修复正常,签到正常 2.所有工具正常 3.接口,i ...