其实吧我老早就把这题切了……因为说实话,这道题确实不难啊……李云龙:比他娘的状压DP简单多了

今天我翻以前在Luogu上写的题解时,突然发现放错代码了,然后被一堆人\(hack\)……蓝瘦啊\(ORZ\)

嗯,还是有些点需要注意以下的!以下是今年4月写的:


\(\mathcal{\color{red}{Description}}\)

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

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

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

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

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

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

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

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

\(\mathcal{\color{red}{Solution}}\)

那么对于这道题而言,先捋清楚题目是求什么的吧:

对于这个无向连通图,我们将每走一步定义为一个阶段。那么每一个阶段都有两种可能性:\(p_i\)的概率去\(d_i\),但是在所有的\(d[i]\) 中\((1<=i<=n)\)至多可以走\(m\)个,\((1-p_i)\)的概率去\(c[i]\)。而我们要求的,就是在这\(n\)个阶段结束之后的路程最小期望。

那么其实状态之间的转移,我们不难看出有两种状态的转移:从\(d[i-1]\)或从\(c[i-1]\)转移过来。而因为实际上对于这个\(DP\)而言,因为数据不大,所以不需要优化什么的\(qwq\),记录每种状态是可行的。

那么很显然啊,我们首先要预处理出每两个点之间的最短路来,方便状态的转移。而在这里,最简单的就是\(Floyd\)啊\(qwq\)。\((n^3\)显然可以接受\()\)

    for(qwq int k=1;k<=v;k++)
for(qwq int i=1;i<=v;i++)
for(qwq int j=1;j<i;j++)
if(f[i][k]+f[k][j]<f[i][j])
f[i][j]=f[j][i]=f[i][k]+f[k][j];

然后就是\(DP\)方程了:

我们定义\(dp[i][j][0/1]\)来表示当前为第\(i\)个阶段,连同这一次已经用了\(j\)次换教室的机会,当前这次换\((1)\)不换\((0)\)的最小期望路程总和。

那么转移就可以如此转移:

这次不换:

\(dp[i][j][0]=\) \(min(\)上次不换的\(dp+\)这两次之间的路程 \(~~\), \(~~\)上次概率换了之后的\(dp+p[i]\times\)上次换了的教室与这次不换的教室之间的距离\(+(1-p[i])\times\)上次不换的教室与这次不换的教室之间的距离\()\)

“诶,为什么上次概率换了之后(即逗号之后的一大串)要加两个期望啊?”

这个问题就是\(rqy\)大佬给我解决的,现在我要农夫山泉一把了:因为在上一次换教室时是“概率”交换,所以不一定会换呀。所以要把两种情况的都加上\(qwq\)。

到这儿我们就可以发现,其实换教室比不换教室是要多一重状态的,因为换教室总要牵扯“概率成功”的问题\(qwq\)

那其实接下来的状态转移方程就很简单了:一次换一次不换,遇到不换就\((1-p[i])\),遇到换就\(p[i]\);两次都不换就不用枚举概率。而且由于牵扯到两次都是概率性事件(比如两次都换)之类的,这个时候需要的就是乘法原理了。

那么\(DP\)即如下:

#define qwq register 

    for(qwq int i=1;i<=n;i++)
for(qwq int j=0;j<=m;j++)
dp[i][j][0]=dp[i][j][1]=999999999; dp[1][0][0]=dp[1][1][1]=0;
for(qwq int i=2;i<=n;i++){
double dist1=f[c[i-1]][c[i]],dist2=f[d[i-1]][c[i]],dist3=f[c[i-1]][d[i]];
for(qwq int j=0;j<=min(m,i);j++)
{
dp[i][j][0]=min(dp[i-1][j][0]+dist1,dp[i-1][j][1]+dist2*p[i-1]+dist1*(1-p[i-1]));
if(j!=0)
dp[i][j][1]=min(dp[i-1][j-1][0]+dist3*p[i]+dist1*(1-p[i]),dp[i-1][j-1][1]+dist1*(1-p[i-1])*(1-p[i])+dist3*(1-p[i-1])*p[i]+dist2*(1-p[i])*p[i-1]+dist2*p[i-1]*p[i]);
}
}

总结:遇到期望的题目时一定要全面考虑啊!我们可以发现这个题的\(dp\)方程其实并不难想。

完结撒花!

//感谢rqy大佬qwqqq
#include<iostream>
#include<cstdio>
#define qwq register
using namespace std;
double p[10001],f[2001][2001],dp[2001][2001][2];
int a[2001][2001],c[20001],d[20001];
inline double min(double a,double b){
return a<b?a:b;
}
inline int qread(){
int k = 0;
char c;
c = getchar();
while(!isdigit(c))c = getchar();
while(isdigit(c)){
k = (k<<1)+(k<<3)+c-48;
c = getchar();
}
return k ;
}
inline double qread_double()
{
double k=0;char c=getchar();
while(!isdigit(c))c=getchar();
while(isdigit(c))k=k*10+(c-48),c=getchar();
if(c=='.')
{
double base=0.1;c=getchar();
while(isdigit(c))k=k+(c-48)*base,base/10,c=getchar();
}
return k;
}
int main()
{
int n,m,v,e,a1,b1,c1;
cin>>n>>m>>v>>e;
for(qwq int i=1;i<=n;i++)c[i]=qread();
for(qwq int i=1;i<=n;i++)d[i]=qread();
for(qwq int i=1;i<=n;i++)p[i]=qread_double(); for(qwq int i=1;i<=v;i++)
for(qwq int j=1;j<i;j++)
f[i][j]=f[j][i]=999999999; for(qwq int i=1;i<=e;i++){
a1=qread(),b1=qread(),c1=qread();
f[a1][b1]=f[b1][a1]=min(f[a1][b1],c1);
} for(qwq int k=1;k<=v;k++)
for(qwq int i=1;i<=v;i++)
for(qwq int j=1;j<i;j++)
if(f[i][k]+f[k][j]<f[i][j])
f[i][j]=f[j][i]=f[i][k]+f[k][j]; for(qwq int i=1;i<=n;i++)
for(qwq int j=0;j<=m;j++)
dp[i][j][0]=dp[i][j][1]=999999999; dp[1][0][0]=dp[1][1][1]=0;
for(qwq int i=2;i<=n;i++){
double add1=f[c[i-1]][c[i]];
for(qwq int j=0;j<=min(m,i);j++)
{
dp[i][j][0]=min(dp[i-1][j][0]+add1,dp[i-1][j][1]+f[d[i-1]][c[i]]*p[i-1]+f[c[i-1]][c[i]]*(1-p[i-1]));
if(j!=0)
dp[i][j][1]=min(dp[i-1][j-1][0]+f[c[i-1]][d[i]]*p[i]+f[c[i-1]][c[i]]*(1-p[i]),dp[i-1][j-1][1]+f[c[i-1]][c[i]]*(1-p[i-1])*(1-p[i])+f[c[i-1]][d[i]]*(1-p[i-1])*p[i]+f[d[i-1]][c[i]]*(1-p[i])*p[i-1]+f[d[i-1]][d[i]]*p[i-1]*p[i]);
}
} double hahaha=9999999999;
for(int i=0;i<=m;i++){
hahaha=min(dp[n][i][0],min(dp[n][i][1],hahaha));}
printf("%.2lf",hahaha);
}

\(By\) \(Flower\) _ \(pks\)

[NOIP2016]换教室(概率期望$DP$)的更多相关文章

  1. [NOIP2016]换教室 D1 T3 Floyed+期望DP

    [NOIP2016]换教室 D1 T3 Description 对于刚上大学的牛牛来说, 他面临的第一个问题是如何根据实际情况中情合适的课程. 在可以选择的课程中,有2n节课程安排在n个时间段上.在第 ...

  2. bzoj4720: [Noip2016]换教室(期望dp)

    4720: [Noip2016]换教室 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1294  Solved: 698[Submit][Status ...

  3. BZOJ 4720 [Noip2016]换教室

    4720: [Noip2016]换教室 Description 对于刚上大学的牛牛来说,他面临的第一个问题是如何根据实际情况申请合适的课程.在可以选择的课程中,有2n节课程安排在n个时间段上.在第i( ...

  4. 【BZOJ】4720: [Noip2016]换教室

    4720: [Noip2016]换教室 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1690  Solved: 979[Submit][Status ...

  5. [NOIP2016]换教室 题解(奇怪的三种状态)

    2558. [NOIP2016]换教室 [题目描述] 对于刚上大学的牛牛来说,他面临的第一个问题是如何根据实际情况申请合适的课程. 在可以选择的课程中,有2n节课程安排在n个时间段上.在第i(1< ...

  6. 【bzoj4720】[NOIP2016]换教室 期望dp

    题目描述 对于刚上大学的牛牛来说,他面临的第一个问题是如何根据实际情况申请合适的课程.在可以选择的课程中,有2n节课程安排在n个时间段上.在第i(1≤i≤n)个时间段上,两节内容相同的课程同时在不同的 ...

  7. 「NOIP2016」「P1850」 换教室(期望dp

    题目描述 对于刚上大学的牛牛来说,他面临的第一个问题是如何根据实际情况申请合适的课程. 在可以选择的课程中,有 2n2n 节课程安排在 nn 个时间段上.在第 ii(1 \leq i \leq n1≤ ...

  8. 【bzoj4720】[NOIP2016]换教室

    题目描述 对于刚上大学的牛牛来说,他面临的第一个问题是如何根据实际情况申请合适的课程.在可以选择的课程中,有2n节课程安排在n个时间段上.在第i(1≤i≤n)个时间段上,两节内容相同的课程同时在不同的 ...

  9. [NOIp2016] 换教室

    题目类型:期望\(DP\) 传送门:>Here< 题意:现有\(N\)个时间段,每个时间段上一节课.如果不申请换教室,那么时间段\(i\)必须去教室\(c[i]\)上课,如果申请换课成功, ...

随机推荐

  1. 5.Resource注解解析

    Resource有两种使用场景 1.Resource 当Resource后面没带参数的时候是根据它所注释的属性名称到applicationContext.xml文件中查找是否有bean的id与之匹配, ...

  2. HTML颜色的三种写法

    颜色的三种写法: 1.16进制代码     #000000 2.英文字母         red 3.rgba                rgba(0-255,0,0,0-1) 例如: <b ...

  3. DOM操作表单

    <!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>& ...

  4. 远景GIS云产品规划

    远景GIS云平台在初期有过产品设计,随着研发工作的进行以及对GIS云的认知更进行一步,最近重新梳理了平台的产品规划,使以后的开发不至于走偏方向. GIS云平台的研发也是摸着石头过河,免不了有考虑不到的 ...

  5. Ubuntu 批量修改图片大小

    现在的相机拍摄出来的照片通常远远大于电脑屏幕,不但尺寸很大,占用磁盘量也很大,我都是拍完照片立马就将其缩小到差不多HD的分辨率 改图片分辨率的软件有很多,除了耳熟能详的PS,Ubuntu下也有开源gi ...

  6. Same Tree 比较两个二叉树是否完全相同

    Given two binary trees, write a function to check if they are equal or not. Two binary trees are con ...

  7. 一次spring aop 切面的问题

    最新项目有个新需求,要在已经写好的controller里面 加上传入参数的验证,由于有多个 controller而且验证每个都要调用其他的服务,故决定采用spring的aop方式. 1.添加aop的验 ...

  8. 搭建高可用mongodb集群(一)——配置mongodb

    在大数据的时代,传统的关系型数据库要能更高的服务必须要解决高并发读写.海量数据高效存储.高可扩展性和高可用性这些难题.不过就是因为这些问题Nosql诞生了. NOSQL有这些优势: 大数据量,可以通过 ...

  9. 13.用别名(alias)创建你自己的命令

    现在是时候,感受第一次编程经历了!我们将用 alias 命令创建我们自己的命令.但在 开始之前,我们需要展示一个命令行小技巧.可以把多个命令放在同一行上,命令之间 用”;”分开.它像这样工作: com ...

  10. Docker bridge探索

    作者:ellen.sun链接:http://blog.daocloud.io/docker-bridge/著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 早期的二层网络中,bri ...