哇好开心啊!写的时候真的全然对于这个加法没有把握,但还是大着胆子试着写了一下——竟然过了样例?于是又调了一下就过啦。

不过想想也觉得是正确的吧,互相独立的事件对于期望的影响自然也是相互独立的,可以把所有的情况看成一个整体,不同的统计方式只是分组的区别,最后算出来的答案肯定是一样的。dp的状态比较显然:dp[i][j][0/1]代表当前在第i节课,已经用去了j次申请的机会,0/1分别代表当前这一节课是否申请。那么这个时候就分情况讨论,计算这一次的选择对于答案的影响。

这些不同的情况分别是:当前和上一次是否选择申请换课,申请换课的是否成功。

期望的计算式:成功的概率*成功的代价+失败的概率*失败的代价。

#include <bits/stdc++.h>
using namespace std;
#define maxn 2050
#define INF 1047483640
#define maxm 2050
#define maxv 400
int n, m, v, e, dis[maxv][maxv], c[maxn], d[maxn];
double ans = , dp[maxn][maxm][], k[maxn]; int read()
{
int x = , k = ;
char c;
c = getchar();
while(c < '' || c > '') { if(c == '-') k = -; c = getchar(); }
while(c >= '' && c <= '') x = x * + c - '', c = getchar();
return x * k;
} void init()
{
for(int i = ; i <= v; i ++)
for(int j = i + ; j <= v; j ++)
dis[i][j] = dis[j][i] = INF; for(int i = ; i <= n; i ++)
for(int j = ; j <= m; j ++)
dp[i][j][] = dp[i][j][] = INF;
} double gmin(double &x, double y)
{
x = (x < y) ? x : y;
} int gmin2(int &x, int y)
{
x = (x < y) ? x : y;
} void Floyd()
{
for(int k = ; k <= v; k ++)
for(int i = ; i <= v; i ++)
for(int j = ; j <= v; j ++)
gmin2(dis[i][j], dis[i][k] + dis[k][j]);
} int main()
{
n = read(), m = read(), v= read(), e = read();
for(int i = ; i <= n; i ++) c[i] = read();
for(int i = ; i <= n; i ++) d[i] = read();
init();
dp[][][] = dp[][][] = ;
for(int i = ; i <= n; i ++) scanf("%lf", &k[i]);
for(int i = ; i <= e; i ++)
{
int x = read(), y = read(), z = read();
dis[x][y] = dis[y][x] = min(dis[y][x], z);
}
for(int i = ; i <= v; i ++) dis[i][i] = ;
Floyd();
for(int i = ; i <= v; i ++)
dis[i][] = dis[][i] = ;
c[] = d[] = , k[] = ;
for(int i = ; i <= n; i ++)
for(int j = ; j <= m; j ++)
{
gmin(dp[i][j][], dp[i - ][j][] + dis[c[i]][c[i - ]]);
gmin(dp[i][j][], dp[i - ][j][] + dis[c[i]][c[i - ]] * ( - k[i - ]) + dis[c[i]][d[i - ]] * k[i - ]);
if(j) gmin(dp[i][j][], dp[i - ][j - ][] + dis[c[i]][c[i - ]] * ( - k[i]) + dis[d[i]][c[i - ]] * k[i]);
double tem = ;
tem += dis[c[i]][c[i - ]] * ( - k[i]) * ( - k[i - ]);
tem += dis[c[i]][d[i - ]] * ( - k[i]) * k[i - ];
tem += dis[d[i]][c[i - ]] * k[i] * ( - k[i - ]);
tem += dis[d[i]][d[i - ]] * k[i] * k[i - ];
if(j) gmin(dp[i][j][], dp[i - ][j - ][] + tem);
}
for(int i = ; i <= m; i ++)
gmin(ans, min(dp[n][i][], dp[n][i][]));
printf("%.2lf", ans);
return ;
}

【题解】NOIP2016换教室的更多相关文章

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

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

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

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

  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. bzoj4720: [Noip2016]换教室(期望dp)

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

  6. 【bzoj4720】[NOIP2016]换教室

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

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

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

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

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

  9. [NOIp2016] 换教室

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

  10. NOIP2016换教室 BZOJ 4720

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

随机推荐

  1. IDEA项目启动报Unable to open debugger port (127.0.0.1:51554): java.net.SocketException "socket closed"

    启动报错: Unable to open debugger port (127.0.0.1:51554): java.net.SocketException "socket closed&q ...

  2. [转]win7下修改C盘USERS文件下的名称

    Win7下C:\Users\Cortana以账户名称命名的系统文件夹用户名的修改   Win7下C:\Users\Cortana以账户名称命名的系统文件夹用户名的修改 Win7下C:\Users\Co ...

  3. Mysql 5.7 开启远程连接

    1 在控制台执行 mysql -uroot -p 系统提示输入数据库root用户的密码,输入完成后即进入mysql控制台 2 选择数据库 mysql -uroot -p use mysql; 开启远程 ...

  4. CacheManager源码分析

    计算rdd的某个分区是从RDD的iterator()方法开始的,我们从这个方法进入 然后我们进入getOrCompute()方法中看看是如何进行读取数据或计算的 getOrElseUpdate()方方 ...

  5. Scala语法(二)

    (1)类,对象 //定义类(属性.方法),实例化对象 class counter{ *//主构造器 class counter(name:String,mode:Int){ ... } 实例化:val ...

  6. python 中 pynlpir错误 Cannot Open Configure file pynlpir\Data\Configure.xml 解决

    在用python做分词.数据处理的时候,想调用pynlpir库,pynlpir.open()时出现错误,更新一下授权文件还是错误, 仔细一看错误是:Cannot Open Configure file ...

  7. Python正则表达式-基础

    Python正则表达式-基础 本文转载自昔日暖阳,原文地址:http://www.osheep.cn/4806.html python使用正则,需要先引入re模块 import re 匹配符 单个字符 ...

  8. Leecode刷题之旅-C语言/python-21.合并两个有序链表

    /* * @lc app=leetcode.cn id=21 lang=c * * [21] 合并两个有序链表 * * https://leetcode-cn.com/problems/merge-t ...

  9. C语言结构体的学习,以及gdb的调式

    #include <stdio.h> #include <string.h> #define format "%d\n%s\n%f\n%f\n%f\n" t ...

  10. 素数环 南阳acm488(回溯法)

    素数环 时间限制:1000 ms  |  内存限制:65535 KB 难度:2   描述 有一个整数n,把从1到n的数字无重复的排列成环,且使每相邻两个数(包括首尾)的和都为素数,称为素数环. 为了简 ...