题目链接:https://www.luogu.org/problemnew/show/P1850

此题正解为dp。

我们先用floyd处理出任意两个教室之间的距离,用dis[i][j]表示。

用f[i][j][0..1]表示在前i个课程中,用了j次换课的机会,第i节课选择换还是不换。

f[i][j][0]可以选择用f[i-1][j][0]更新(即第i-1节课选择不换课),代价为dis[c[i-1]][c[i]]。

同时,第i-1节课也可以选择换课,若换课成功,代价为dis[d[i-1]][c[i]],概率为k[i-1]。若换课不成功,则代价还是dis[c[i-1]][c[i]],概率为(1-k[i-1])。

则f[i][j][0]=min(f[i-1][j][0]+dis[c[i-1]][c[i]],(f[i-1][j-1][1]+dis[d[i-1]][c[i]])*k[i-1]+(f[i-1][j][0]+dis[c[i-1]][c[i]])*(1-k));

同理,f[i][j][1]可以选择用f[i-1][j][0]更新,若换课成功,代价为dis[c[i-1]][d[i]],概率为k[i]。若换课不成功,则代价是dis[c[i-1]][c[i]],概率为(1-k[i])。

同时,f[i][j][1]也可以选择用f[i-1][j][1]更新。

若两次换课均成功,代价为dis[d[i-1]][d[i]],概率为k[i]*k[i-1]。

若两次换课均不成功,代价为dis[c[i-1]][c[i]],概率为(1-k[i])*(1-k[i-1])。

若第i次成功而第i-1次不成功,代价为dis[c[i-1]][d[i]],概率为(1-k[i-1])*k[i]。

若第i次不成功而第i-1次成功,代价为dis[d[i-1]][c[i]],概率为k[i-1]*(1-k[i])。

则f[i][j][1]=min((f[i-1][j][0]+dis[c[i-1]][d[i]])*k[i]+(f[i-1][j][0]+dis[c[i-1]][c[i]])*(1-k[i]),f[i-1][j][1] + dis[d[i-1]][d[i]]*k[i]*k[i-1] + dis[c[i-1]][c[i]]*(1-k[i])*(1-k[i-1]) + dis[c[i-1]][d[i]]*(1-k[i-1])*k[i] + dis[d[i-1]][c[i]]*k[i-1]*(1-k[i]))。

可以看出每次转移是O(1)的,则时间复杂度为O(n*m)+O(v^3)。

最终结果为min(f[n][i][k]) i∈[0,m],j∈[0,1]。

 #include<iostream>
#include<cstdio>
#include<cstring>
#define M 2002
using namespace std;
int n,m,v,e,c[M]={},d[M]={};
double p[M]={},dis[][]={},f[M][M][]={},minn=;
void pmin(double &x,double y){
x=min(x,y);
} int main(){
scanf("%d%d%d%d",&n,&m,&v,&e);
for(int i=;i<=n;i++) scanf("%d",c+i);
for(int i=;i<=n;i++) scanf("%d",d+i);
for(int i=;i<=n;i++) scanf("%lf",p+i);
for(int i=;i<=v;i++)
for(int j=;j<=v;j++) dis[i][j]=;
for(int i=;i<=e;i++){
int x,y,z;scanf("%d%d%d",&x,&y,&z);
pmin(dis[x][y],z); pmin(dis[y][x],z);
}
for(int i=;i<=v;i++) dis[i][i]=;
for(int k=;k<=v;k++)
for(int i=;i<=v;i++)
for(int j=;j<=v;j++)
dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
for(int i=;i<=n;i++)
for(int j=;j<=m;j++) f[i][j][]=f[i][j][]=;
f[][][]=; f[][][]=;
for(int i=;i<n;i++)
for(int j=;j<=min(i,m);j++){
pmin(f[i+][j][],f[i][j][]+dis[c[i]][c[i+]]);
double px;px=dis[c[i]][d[i+]]*p[i+]+dis[c[i]][c[i+]]*(-p[i+]);
pmin(f[i+][j+][],f[i][j][]+px);
px=dis[d[i]][c[i+]]*p[i]+dis[c[i]][c[i+]]*(-p[i]);
pmin(f[i+][j][],f[i][j][]+px);
px=dis[d[i]][d[i+]]*p[i]*p[i+]+dis[d[i]][c[i+]]*p[i]*(-p[i+])+dis[c[i]][d[i+]]*(-p[i])*p[i+]+dis[c[i]][c[i+]]*(-p[i])*(-p[i+]);
pmin(f[i+][j+][],f[i][j][]+px);
} for(int i=;i<=m;i++){
minn=min(minn,f[n][i][]);
minn=min(minn,f[n][i][]);
}
printf("%.2lf\n",minn);
}

【NOIP2016提高组】 Day1 T3 换教室的更多相关文章

  1. 【NOIP2016提高组day1】†换教室

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

  2. 【NOIP2016】Day1 T3 换教室(期望DP)

    题目背景 NOIP2016 提高组 Day1 T3 题目描述 对于刚上大学的牛牛来说,他面临的第一个问题是如何根据实际情况申请合适的课程. 在可以选择的课程中,有 2n 节课程安排在 n 个时间段上. ...

  3. Noip2011 提高组 Day1 T3 Mayan游戏

    题目描述 Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个 7 行5 列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他方块之上.游戏通关是指在规定 ...

  4. Noip2016 提高组 Day1

    T1 玩具迷题 直通 思路: 1.首先根据数据范围来看,储存小人的姓名开一个二维char数组即可(不会开爆) 2.然后看他给出的样例以及条件什么的,能够确定出 ①朝内向右,朝外向左均为+ ②朝内向左, ...

  5. NOIP2016 DAY1 T3 换教室

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

  6. 2012Noip提高组Day1 T3 开车旅行

    题目描述 小 A 和小 B 决定利用假期外出旅行,他们将想去的城市从 1 到 N 编号,且编号较小的 城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市 i 的海拔高度为 Hi,城市 ...

  7. NOIP2011提高组 Day1 T3 Mayan游戏

    题目描述 Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个7行×5列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他方块之上.游戏通关是指在规定的步 ...

  8. 洛谷 3953 NOIP2017提高组Day1 T3 逛公园

    [题解] 先建反向图,用dijkstra跑出每个点到n的最短距离dis[i] 设f[u][k]表示dis(u,n)<=mindis(u,n)+k的方案数.对于边e(u,v,w),走了这条边的话需 ...

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

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

随机推荐

  1. 201521123117 《Java程序设计》第2周学习总结

    本周学习总结: 1.String常量,创建之后不能再进行修改 2.类管理机制是包. 3.Java数组的使用. 书面作业: Q1:使用Eclipse关联jdk源代码,并查看String对象的源代码(截图 ...

  2. php中的多条件查询

    首先是查询所有,步骤不详述,连接数据库,查询表中的所有信息,foreach循环以表格的形式打印出来 然后就是form表单中提交查询的数据,这里以post方式提交到本页面,所以要判断post中是否有值, ...

  3. php中文分词

    主要列出现知道的几个工具: 1,scws中文分词支持php7 http://www.xunsearch.com/scws/index.php 2,phpanalysis中文分词,主要使用了机械分词方法 ...

  4. ionic 打包安卓包

    一.配置环境: 先按照之前的文章,配置好环境需要: 二.安装 1. 这里前提是 需要安装  node (地址: http://nodejs.cn/download/) 命令: node -v   // ...

  5. Python爬虫1-----------placekitten 入门

    常用的urllib库有三个类:request,parse,error,request主要完成对url的请求,如proxy,opener,urlopen,parse主要完成对html的解析,error负 ...

  6. 接口测试入门(2)--get和post初级请求/使用httpclient做一个获取信息list的请求(需要登录才可以)

    抛去测试自动化的架构来,直接写单个测试用例的思路如下: 1.获取测试case的接口,对每一个接口的请求方式(get/post/delete/put)进行分析,是否需要参数(不同的用例设置不同的参数,如 ...

  7. JVM(四)内存回收(二)

    在上一节中"JVM(三)内存回收(一)"我讲到了垃圾回收的几种算法,算是解决了之前提到的3个问题中的最后一个. 关于内存回收,还应该了解常用的内存回收器(GC Collector) ...

  8. 关于ng-options

    在实际使用过程中对angular的ng-options指令有点不解,有的时候觉得很容易理解和上手,但其实等到遇到问题时,发现它很是生疏,(key,value)键值对获取,as关键词,track by ...

  9. 云计算之openstack ocata 项目搭建详细方法

    之前写过一篇<openstack mitaka 配置详解>然而最近使用发现阿里不再提供m版本的源,所以最近又开始学习ocata版本,并进行总结,写下如下文档 OpenStack ocata ...

  10. Count(*), Count(1) 和Count(字段)的区别

    1.  count(1) and count(*) 当表的数据量大些时,对表作分析之后,使用count(1)还要比使用count(*)用时多了!  从执行计划来看,count(1)和count(*)的 ...