题目描述

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

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

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

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

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

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

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

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

输入输出格式

输入格式:

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

第二行 nn 个正整数,第 ii(1
\leq i \leq n1≤i≤n)个正整数表示 c_ic​i​​,即第 ii 个时间段牛牛被安排上课的教室;保证 1
\le c_i \le v1≤c​i​​≤v。

第三行 nn 个正整数,第 ii(1
\leq i \leq n1≤i≤n)个正整数表示 d_id​i​​,即第 ii 个时间段另一间上同样课程的教室;保证 1
\le d_i \le v1≤d​i​​≤v。

第四行 nn 个实数,第 ii(1
\leq i \leq n1≤i≤n)个实数表示 k_ik​i​​,即牛牛申请在第 ii 个时间段更换教室获得通过的概率。保证 0
\le k_i \le 10≤k​i​​≤1。

接下来 ee 行,每行三个正整数 a_j,
b_j, w_ja​j​​,b​j​​,w​j​​,表示有一条双向道路连接教室 a_j,
b_ja​j​​,b​j​​,通过这条道路需要耗费的体力值是 w_jw​j​​;保证 1
\le a_j, b_j \le v1≤a​j​​,b​j​​≤v, 1
\le w_j \le 1001≤w​j​​≤100。

保证 1
\leq n \leq 20001≤n≤2000,0
\leq m \leq 20000≤m≤2000,1
\leq v \leq 3001≤v≤300,0
\leq e \leq 900000≤e≤90000。

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

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

输出格式:

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

测试数据保证四舍五入后的答案和准确答案的差的绝对值不大于 4
\times 10^{-3}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说明】

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

【提示】

  1. 道路中可能会有多条双向道路连接相同的两间教室。 也有可能有道路两端连接

的是同一间教室。

2.请注意区分n,m,v,e的意义, n不是教室的数量, m不是道路的数量。

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

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

题解

floyd算法

floyd算法是解决的所有点对之间的最短路的算法,复杂度O(n^3)
采用的是dp的思想,每次以一个节点为中介点更新最短路
d[i][j]表示i->j的最短路,初始d[i][j]要么为边权要么为INF

代码极其简洁:
void floyd(){
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(d[i][k]+d[k][j]<d[i][j])
d[i][j]=d[i][k]+d[k][j];
}

概率dp

概率dp,顾名思义,就是有关概率的dp,它的状态通常是f.....[1],f......[0],1、0等表示选择,转移时各自乘上各自实现的概率进行转移


本题题解

首先v<=300明显可以要用floyd算法算出点对最短路
然后设f[i][j][0 or 1]为i时刻总共用了j次申请机会到 0号或1号【表示该时刻的两个教室】 教室的最短路径
根据概率dp的思想,状态转移方程就是这样的:
f[i][j][0]=min(f[i-1][j][0]+d[a[i-1]][a[i]],f[i-1][j][1]+d[a[i-1]][a[i]]*(1-c[i-1])+d[b[i-1]][a[i]]*c[i-1]);
f[i][j][1]=min(f[i-1][j-1][0]+d[a[i-1]][a[i]]*(1-c[i])+d[a[i-1]][b[i]]*c[i],
f[i-1][j-1][1]
+d[a[i-1]][a[i]]*(1-c[i-1])*(1-c[i])
+d[b[i-1]][a[i]]*c[i-1]*(1-c[i])
+d[a[i-1]][b[i]]*(1-c[i-1])*c[i]
+d[b[i-1]][b[i]]*c[i-1]*c[i]);

= =方程太长,反正就是分类讨论嘛
然后初始化第一个时间点f[1][0][0]=f[1][1][1]=0
其他时间为INF


#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long int
using namespace std;
const int maxn=2005,maxv=305,INF=1000000000,P=1000000007; inline int read(){
int out=0,flag=1;char c=getchar();
while(c<48||c>57) {if(c=='-') flag=-1;c=getchar();}
while(c>=48&&c<=57){out=out*10+c-48;c=getchar();}
return out*flag;
} int n,m,v,e,a[maxn],b[maxn];
int d[maxv][maxv];
double c[maxn],f[maxn][maxn][2]; void init(){
int x,y,z;
n=read();m=read();v=read();e=read();
for(int i=1;i<=n;i++) a[i]=read();
for(int i=1;i<=n;i++) b[i]=read();
for(int i=1;i<=n;i++) scanf("%lf",&c[i]);
fill(d[0],d[0]+maxv*maxv,INF);
for(int i=1;i<=v;i++) d[i][i]=0;
while(e--){
x=read();
y=read();
z=read();
if(x==y) continue;
if(z<d[x][y]) d[x][y]=d[y][x]=z;
}
} void floyd(){
for (int k=1; k<=v; k++)
for (int i=1; i<=v; i++)
for (int j=1; j<=v; j++)
if (d[i][k] + d[k][j] < d[i][j])
d[i][j] = d[i][k] + d[k][j];
} void solve(){
for (int i=0; i<n; i++)
for (int j=0; j<n; j++)
f[i][j][0] = f[i][j][1] = INF;
f[1][0][0] = 0; f[1][1][1] = 0;
for(int i=2;i<=n;i++){
f[i][0][0]=f[i-1][0][0]+d[a[i-1]][a[i]];
for(int j=1;j<=min(i,m);j++){
f[i][j][0]=min(f[i-1][j][0]+d[a[i-1]][a[i]],f[i-1][j][1]+d[a[i-1]][a[i]]*(1-c[i-1])+d[b[i-1]][a[i]]*c[i-1]);
f[i][j][1]=min(f[i-1][j-1][0]+d[a[i-1]][a[i]]*(1-c[i])+d[a[i-1]][b[i]]*c[i],
f[i-1][j-1][1]
+d[a[i-1]][a[i]]*(1-c[i-1])*(1-c[i])
+d[b[i-1]][a[i]]*c[i-1]*(1-c[i])
+d[a[i-1]][b[i]]*(1-c[i-1])*c[i]
+d[b[i-1]][b[i]]*c[i-1]*c[i]);
}
}
} void print(){
double ans=f[n][0][0];
for(int i=1;i<=m;i++){
if(f[n][i][0]<ans) ans=f[n][i][0];
if(f[n][i][1]<ans) ans=f[n][i][1];
}
printf("%.2lf\n",ans);
} int main(){
init();
floyd();
solve();
print();
return 0;
}


[NOIP2016 D1T3]换教室 【floyd+概率dp】的更多相关文章

  1. LOJ2360. 「NOIP2016」换教室【概率DP】【Floyed】【傻逼题】

    LINK 思路 先floyed出两点最短路 然后就可以直接\(dp_{i,j,0/1}\)表示前i节课选择换j节,换不换当前这一节的最小贡献 直接可以枚举上一次决策的状态计算概率进行统计就可以了 我变 ...

  2. NOIP2016D1T3 换教室 (概率DP)

    NOIP2016D1T3 换教室 题目大意:有n个时间段,每个时间段i有两个教室a[i],b[i]可以上课,如果不申请换教室就在教室a[i]上课,如果换教室就在b[i]上课.你最多只能换m次教室.教室 ...

  3. 洛谷P1850 换教室(概率dp)

    传送门 我的floyd竟然写错了?今年NOIP怕不是要爆零了? 这就是一个概率dp 我们用$dp[i][j][k]$表示在第$i$个时间段,已经申请了$j$次,$k$表示本次换或不换,然后直接暴力转移 ...

  4. NOIP2016Day1T3换教室(floyd+期望dp)

    啊...这个时间写博客,明天还要上学,整个人都不好了... 这是我写的第一道期望题hiahiahia... 题目大意就不说了QWQ 80分儿做法:先floyd,爆搜枚举哪些点取,求出答案,效率O(C( ...

  5. [NOIP2016]换教室(概率期望$DP$)

    其实吧我老早就把这题切了--因为说实话,这道题确实不难啊--李云龙:比他娘的状压DP简单多了 今天我翻以前在Luogu上写的题解时,突然发现放错代码了,然后被一堆人\(hack\)--蓝瘦啊\(ORZ ...

  6. [NOIP2016][luogu]换教室[DP]

    [NOIP2016] Day1 T3 换教室 ——!x^n+y^n=z^n 题目描述 对于刚上大学的牛牛来说,他面临的第一个问题是如何根据实际情况申请合适的课程. 在可以选择的课程中,有 2n 节课程 ...

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

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

  8. 【BZOJ4720】【NOIP2016】换教室 [期望DP]

    换教室 Time Limit: 20 Sec  Memory Limit: 512 MB[Submit][Status][Discuss] Description Input 第一行四个整数n,m,v ...

  9. 【NOIP2016】换教室 题解(期望DP)

    前言:状态贼鸡儿多,眼睛快瞎了. ----------------------- 题目链接 题目大意:给定$n(课程数),m(可换次数),v(教室数),e(无向边数)$,同时给定原定教室$c[i]$和 ...

随机推荐

  1. 二、Web框架实现

    一.简单web(socket) 在前一篇WEB框架概述一文中已经详细了解了:从浏览器键入一个URL到返回HTML内容的整个过程.说到底,本质上其实就是一个socket服务端,用户的浏览器其实就是一个s ...

  2. HTML基本代码教学片,认识HTML

    今儿头午有点晕晕的感觉,咳咳,甩甩头开课 HTML 定义:超文本标记语言 (记不住的可以这么记:how to make love ! 哈哈,准备开车,粗人一个,长的不行) 其实理解起来很简单,超越文本 ...

  3. Java+Selenium 3.x 实现Web自动化 - Maven打包TestNG,利用jenkins执行测试

    1. Jenkins本地执行测试 or 服务器端执行测试 测试代码计划通过jenkins执行时,通过网上查询各种教程,大多数为本地执行测试,由此可见,本地执行是大多数人的选择. 经过探讨,最终决定采用 ...

  4. Unity Lighting - Emissive Materials 自发光材质(九)

      Emissive Materials 自发光材质 Whilst Area Lights are not supported by Precomputed Realtime GI, similar ...

  5. python编辑购物车

    一.需求分析 输入工资金额,进入购物车,并打印输出商品编号和价格,用户可以通过输入商品编号进行商品选购 余额不足时,打印提示信息 通过q进行退出结算 购物车能够循环购物 二.代码实现 ShoopCar ...

  6. CF 1008B Turn the Rectangles(水题+贪心)

    There are n rectangles in a row. You can either turn each rectangle by 90 degrees or leave it as it ...

  7. Alpha 冲刺(10/10)

    队名 火箭少男100 组长博客 林燊大哥 作业博客 Alpha 冲鸭鸭鸭鸭鸭鸭鸭鸭鸭鸭! 成员冲刺阶段情况 林燊(组长) 过去两天完成了哪些任务 协调各成员之间的工作 测试整体软件 展示GitHub当 ...

  8. URL相关Web APIs

    参考文档:MDN> Web API接口 > URLUtils MDN > Web API接口 > URL MDN > Web API接口 > Location MD ...

  9. lintcode-436-最大正方形

    436-最大正方形 在一个二维01矩阵中找到全为1的最大正方形 样例 1 0 1 0 0 1 0 1 1 1 1 1 1 1 1 1 0 0 1 0 返回 4 标签 动态规划 爱彼迎 脸书 思路 使用 ...

  10. JavaScript设计模式学习之路——面向对象的思想

    今天,我拿到了张容铭写的这本<JavaScript设计模式>这本书,开始了关于JavaScript更深一点的学习. 看到这本书开始的时候,虽然之前通过看书.一些比较好的视频的讲解,对Jav ...