NOIP2016 换教室
来源:互联网 发布:sqlserver服务器配置 编辑:程序博客网 时间:2024/05/18 02:22
题解在下面
题目大意: 牛牛每天需要学完大学里的 n 门课程,每门课程有 2 节课 ci 和 di,这两节课会被安排在不同的教室上课。对于每门课程,牛牛可以任选一节课学习。每次上课,牛牛需要从一间教室 ai 走到另一间教室 bi,这就需要耗费他一些体力 wi。
现在,大学提供了换课的机会,对于每门课程,你可以选择换课,换课成功的概率为 ki。牛牛最多可以换 m 节课(当然他也可以选择不用完这 m 次机会)。换课之后,牛牛就可以到另外一间教室上课。
牛牛所在的大学有 v 间教室,e 条道路,每条道路连接两间教室,并且是可以双向通行的。对于每条道路,耗费的体力 wi 不一定相同。当第 i ( 1 ≤ i ≤ n−1 )节课结束后,牛牛就会从这节课的教室出发,选择一条耗费体力最少的路径前往下一节课的教室。
现在牛牛想知道,申请这些课程中的哪节课可以使他因在教室间移动耗费的体力值的总和的期望值最小,请你帮他求出这个最小值。
输入:
第一行四个整数 n, m, v, e ,表示有 n 节课,m 次换课的机会,v 间教室和 e 条道路。
第二行 n 个正整数,第 i ( 1 ≤ i ≤ n )个正整数表示 ci ,即第 i 个时间段牛牛被安排上课的教室;保证 1 ≤ ci ≤ v 。
第三行 n 个正整数,第 i ( 1 ≤ i ≤ n )个正整数表示 di ,即第 i 个时间段另一间上同样课程的教室;保证 1 ≤ di ≤ v 。
第四行 n 个实数,第 i ( 1 ≤ i ≤ n )个实数表示 ki ,即牛牛申请在第 i 个时间段更换教室获得通过的概率。保证 0 ≤ ki ≤ 1 。
接下来 e 行,每行三个正整数 aj , bj , wj ,表示有一条双向道路连接教室 aj , bj ,通过这条道路需要耗费的体力值是 wj ;保证 1 ≤ aj, bj ≤ v , 1 ≤ wj ≤ 100 。
保证 1 ≤ n ≤ 2000 , 0 ≤ m ≤ 2000 , 1 ≤ v ≤ 300 , 0 ≤ e ≤ 90000。
保证通过学校里的道路,从任何一间教室出发,都能到达其他所有的教室。可能有两条道路连着同一间教室的情况。
输出:
输出一行,包含一个实数,四舍五入精确到小数点后恰好 2
位,表示答案。
题目分析:
由题,这道题的 n 和 m 仅为 2000,并且教室的数量 v 仅有 300。而牛牛每次要选择走最短的路到另一个教室,所以我们需要用 Floyd 求出任意两个教室之间的最短距离。
之后,根据题意,我们需要求出最后的期望移动距离,再加上 n 和 m 的数据规模的提示,我们可以使用期望 DP 的思想来解决这道题。
我们用
那么对于每一节课,它只有选或不选两种状态,并且可以由上一节课选或不选转移过来,因此我们可以很容易地得到 DP 方程,每个
对于
最后,再看
下面附上代码:
- #include<cstdio>
- #include<cstring>
- #include<algorithm>
- using namespace std;
- const int MX=2005;
- const int MXE=305;
- int n,m,v,e;
- int c[MX],d[MX],dis[MXE][MXE];
- double p[MX],dp[MX][MX][2];
- void floyd(){
- for (int k=1;k<=v;k++)
- for (int i=1;i<=v;i++)
- for (int j=1;j<=v;j++)
- dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
- }
- void solve(){
- dp[0][0][0]=0,dp[1][0][0]=0,dp[1][1][1]=0;
- for (int i=2;i<=n;i++){
- for (int j=0;j<=m;j++){
- //分为两个状态:这节课换课和这节课不换课
- //每种状态对应另外两个状态:上节课换课和上节课不换课
- //总共 4 种状态,如下
- dp[i][j][0]=min(dp[i-1][j][0] + dis[c[i-1]][c[i]],dp[i-1][j][1] + p[i-1]*dis[d[i-1]][c[i]] + (1-p[i-1])*dis[c[i-1]][c[i]]);
- dp[i][j][1]=min(dp[i-1][j-1][0] + p[i]*dis[c[i-1]][d[i]] + (1-p[i])*dis[c[i-1]][c[i]],dp[i-1][j-1][1] + p[i-1]*(p[i]*dis[d[i-1]][d[i]] + (1-p[i])*dis[d[i-1]][c[i]]) + (1-p[i-1])*(p[i]*dis[c[i-1]][d[i]] + (1-p[i])*dis[c[i-1]][c[i]]));
- }
- }
- }
- int main(){
- //初始化
- memset(dis,0x3f,sizeof(dis));
- memset(dp,0x44,sizeof(dp));
- int a,b,len;
- 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;i<=v;i++) dis[i][i]=0;
- for (int i=1;i<=e;i++){
- scanf(”%d%d%d”,&a,&b,&len);
- if (a!=b){
- dis[a][b]=min(dis[a][b],len);
- dis[b][a]=min(dis[b][a],len);
- }
- }
- floyd();
- solve();//DP
- double minv=1e20;
- for (int i=0;i<=m;i++){ //取最小值
- minv=min(min(dp[n][i][0],dp[n][i][1]),minv);
- }
- printf(”%0.2lf”,minv);
- return 0;
- }
- BZOJ4720 [Noip2016]换教室
- [NOIP2016]换教室
- [NOIP2016] 换教室
- 【noip2016】换教室 题解
- NOIP2016 换教室
- bzoj4720 [Noip2016]换教室
- NOIP2016换教室
- NOIP2016 T3 换教室
- 【NOIP2016-D1T3】换教室
- NOIP2016 换教室
- bzoj4720: [Noip2016]换教室
- bzoj4720 [Noip2016]换教室
- noip2016换教室
- 【NOIP2016】换教室
- [noip2016]换教室 题解
- [NOIP2016] 换教室
- NOIP2016换教室
- 【noip2016】换教室
- linux 网络配置
- 剑指OFFER纪念版(4)
- Bigtable: A Distributed Storage System for Structured Data : part2 Data Model (数据模型)
- 欧拉回路/路径【总结】
- 使用js计算距离2017年10月1日00:00时间
- NOIP2016 换教室
- UVA11865[Stream My Contest] 朱刘算法求最小树形图
- 浏览器history对象初窥
- JqueryForm
- JQuery EasyUI 之LinkButton(按钮)组件
- 内存分配及变量存储位置(堆、栈、方法区常量池、方法区静态区)
- 手机号码4位隐藏
- Mybaitis逆向工程
- shell脚本搭建容器云完结篇(三)