做完这道题才略微感觉自己懂了一点关于概率与期望的知识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;
}

最新文章

  1. Tomcat性能调优方案
  2. MVP 实例
  3. tar命令参数笔记
  4. [最短路径SPFA] POJ 1847 Tram
  5. guava学习--Optional可空类型
  6. html5 中meta中 content=width=device-width注意
  7. BBED的安装及简单的使用方法
  8. 2014.3.4-C语言学习小结
  9. PHP批量上传一次点击选中多个
  10. 2015-2016 ACM-ICPC, NEERC, Southern Subregional Contest A Email Aliases(模拟STL vector+map)
  11. java设计模式—— 工厂模式
  12. Mysql:查询每个月下的数据,根据状态或者年份的sql语句
  13. 当使用vue的按键修饰符不起效果的时候怎么办?如@keyup.enter = &#39;&#39; ;
  14. Python字符串与格式化的一点用法
  15. php三级联动(html,php两个页面)
  16. 调用Microsoft.Office.Interop.Word生成自定义Word文档
  17. Lucene系列六:Lucene搜索详解(Lucene搜索流程详解、搜索核心API详解、基本查询详解、QueryParser详解)
  18. springbatch----&gt;springbatch的使用(四)
  19. 雷林鹏分享:Ruby 安装 - Windows
  20. Battle City 优先队列+bfs

热门文章

  1. 将本地代码上传到云效git存放
  2. 前端基础问题:CSS vertical-align 属性
  3. MySQL数据迁移那些事儿
  4. (转)elasticsearch连接不到head插件解决方案
  5. ES6学习-1 啥是ES6啊
  6. Linux服务之Samba服务篇
  7. 关于typedef的用法总结-(转自Bigcoder)
  8. numpy tile()函数
  9. Linux 查看实时网卡流量的方法 网速 nload sar iftop dstat
  10. F5 api接口开发实战手册(二)