Noip2016 换教室(数学期望入门)

题意:有2n个课程安排在n个时间段上,在第i个时间被安排在ci教室上课,但牛牛可以申请换教室,到di教室上课,但只有pi的可能成功。学校有v个教室,e条道路,每条路双向连通,每条路都会消耗一定的体力wi(保证每个教室可以互相到达),问牛牛应该怎么安排,才能使总花费的体力的期望值最小。

输入格式:

第一行四个整数n,m,v,e。n表示时间短的数量;m表示最多可以申请更换教室的数量;v表示教室的数量;e表示道路的数量。

第二行n个正整数,第i个表示ci;

第三行n个正整数,第i个表示di;

第四行n个实数,第i个表示pi;

接下来e行,每行三个正整数ai,bi,wi,表示,有一条双向道路连通ai与bi,消耗的体力为wi;

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

输出格式:

输出一行,包含一个实数,四舍五入到小数点后两位,表示答案。

输入样例:

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

输出样例:

2.80

解析:一道数学期望的入门题,dp的方程不难想,dp[i][j][k] 表示前i个教室,换了j次教室,第i个点有没有换所走的最小期望距离。显然 dp[i][j][0] = max(dp[i-1][j][0] + 所需的代价, dp[i-1][j][1] + 所需的代价),dp[i][j][1] = max(dp[i-1][j-1][0] + 所需的代价, dp[i-1][j-1][1] + 所需的代价)。本题的关键便在“所需的代价”上(状态转移特别毒瘤)。转移如下:

dp[i][j][0] = max(dp[i-1][j][0] + 上一个教室与这一个教室的距离, dp[i-1][j][1] + 上一次换教室与这一次的距离*上次换教室成功的几率 + 上一次没换教室与这一次的距离*上一次换教室不成功的几率);

dp[i][j][1] = max(dp[i-1][j-1][0] + 上一个教室与这个教室换了教室的距离*这个教室换成功的几率 + 上一个教室与这个教室的距离*这个教室换不成功的几率, dp[i-1][j-1][1] + 上一个教室换了与这个教室换了的距离*上个教室换成功的几率*这个教室换成功的几率 + 上一个教室与这个教室的距离*上个教室换不成功的几率*这个教室换不成功的几率 + 上一个教室换了与这个教室的距离*上个教室换成功的几率*这个教室换不成功的几率 + 上个教室与这个教室换了的距离*上个教室换不成功的几率*这个教室换成功的几率);

注意:换教室成功的几率为pi, 则不成功的几率则为(1-pi)。

转移特别麻烦,而且也特别长。

代码如下:

#include<cstdio>
#include<algorithm>
using namespace std;

int n,m,v,e,w[301][301],c[2001],d[2001];
double p[2001],dp[2001][2001][2],ans=2e9;

void floyd(void) {  //floyd预处理每个教室之间的距离
    for (int k=1;k<=v;++k)
      for (int i=1;i<=v;++i)
        for (int j=1;j<=v;++j)
          w[i][j]=min(w[i][j],w[i][k]+w[k][j]);
}

int main() {
    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)
        for (int j=1;j<i;++j) w[i][j]=w[j][i]=1e9;
      for (int i=1;i<=e;++i) {
          int x,y,v; scanf("%d%d%d",&x,&y,&v);
          w[x][y]=w[y][x]=min(w[x][y],v);  //处理重边
      }
    floyd();
      for (int i=1;i<=n;++i)
        for (int j=0;j<=m;++j) dp[i][j][1]=dp[i][j][0]=1e9;
    dp[1][0][0]=dp[1][1][1]=0;  //dp初始化
      for (int i=2;i<=n;++i)
        for (int j=0;j<=min(i,m);++j) {  //恶心的转移
          dp[i][j][0]=min(dp[i][j][0],min(dp[i-1][j][0]+w[c[i-1]][c[i]],dp[i-1][j][1]+w[d[i-1]][c[i]]*p[i-1]+w[c[i-1]][c[i]]*(1-p[i-1])));
          if (j>0) dp[i][j][1]=min(dp[i][j][1],min(dp[i-1][j-1][0]+w[c[i-1]][d[i]]*p[i]+w[c[i-1]][c[i]]*(1-p[i]),dp[i-1][j-1][1]+w[d[i-1]][d[i]]*p[i-1]*p[i]+w[c[i-1]][c[i]]*(1-p[i-1])*(1-p[i])+w[c[i-1]][d[i]]*(1-p[i-1])*p[i]+w[d[i-1]][c[i]]*p[i-1]*(1-p[i])));
        }
      for (int i=0;i<=m;++i) ans=min(ans,min(dp[n][i][1],dp[n][i][0]));  //不一定要用完所有换教室的机会,所以取min
    printf("%.2lf",ans);
    return 0;
}

原文地址:https://www.cnblogs.com/Gaxc/p/9507211.html

时间: 2024-08-27 22:52:19

Noip2016 换教室(数学期望入门)的相关文章

bzoj 4720: [Noip2016]换教室【期望dp】

状压dp,设f[i][j][0/1]为前i个时间段换了j间教室的期望体力消耗,转移很好想(但是写起来好长= =) #include<iostream> #include<cstdio> using namespace std; const int N=2005; int n,m,v,e,c[N],d[N]; double k[N],f[N][N][2],ans=1e9,a[N][N],z; int read() { int r=0,f=1; char p=getchar(); wh

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

[NOIP2016]换教室 D1 T3 Description 对于刚上大学的牛牛来说, 他面临的第一个问题是如何根据实际情况中情合适的课程. 在可以选择的课程中,有2n节课程安排在n个时间段上.在第 i ( 1≤ i≤n)个时同段上, 两节内容相同的课程同时在不同的地点进行, 其中, 牛牛预先被安排在教室 ci上课, 而另一节课程在教室 di进行. 在不提交任何申请的情况下,学生们需要按时间段的顺序依次完成所有的n节安排好的课程.如果学生想更换第i节课程的教室,则需要提出中情.若申请通过,学生

BZOJ 4720 [Noip2016]换教室

4720: [Noip2016]换教室 Description 对于刚上大学的牛牛来说,他面临的第一个问题是如何根据实际情况申请合适的课程.在可以选择的课程中,有2n节课程安排在n个时间段上.在第i(1≤i≤n)个时间段上,两节内容相同的课程同时在不同的地点进行,其中,牛牛预先被安排在教室ci上课,而另一节课程在教室di进行.在不提交任何申请的情况下,学生们需要按时间段的顺序依次完成所有的n节安排好的课程.如果学生想更换第i节课程的教室,则需要提出申请.若申请通过,学生就可以在第i个时间段去教室

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

2558. [NOIP2016]换教室 [题目描述] 对于刚上大学的牛牛来说,他面临的第一个问题是如何根据实际情况申请合适的课程. 在可以选择的课程中,有2n节课程安排在n个时间段上.在第i(1<i<n)个时间段上,两节内容相同的课程同时在不同的地点进行,其中,牛牛预先被安排在教室ci上课,而另一节课程在教室di进行. 在不提交任何申请的情况下,学生们需要按时间段的顺序依次完成所有的n节安排好的课程.如果学生想更换第i节课程的教室,则需要提出申请.若申请通过,学生就可以在第i个时间段去教室di

BZOJ P4720[Noip2016]换教室____solution

题目太长不表 <--无形传送,最为致命 学习一点数学期望的基础,预处理最短路,然后加上DP即可.(废话) 理解决策和结果的差别: 在这里每阶段的决策有两个:申请|不申请 结果有两个:换|不换 然而二者不是一一对应的关系: 而且决策意味着状态,结果只用于计算期望 为什么呢 因为答案要的就是对于某种决策组的期望 于是状态的设计应该是分为申请|不申请, 然后计算期望时讨论申请成不成功: 状态:f[i,j,0/1]讨论前i节课,申请j次,第三维=[第i节申请了] 方程: //f[i][j][0]=f[i

JZYZOJ1457 [NOIP2016]换教室 期望dp 动态规划 floyd算法 最短路

http://172.20.6.3/Problem_Show.asp?id=1457 我不知道为什么我倒着推期望只有80分,所以我妥协了,我对着题解写了个正的,我有罪. 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cmath> 5 #include<iostream> 6 #include<queue> 7 using namespac

noip2016 换教室

题目描述 对于刚上大学的牛牛来说, 他面临的第一个问题是如何根据实际情况中情合适的课程. 在可以选择的课程中,有2n节课程安排在n个时间段上.在第 i ( 1≤ i≤n)个时同段上, 两节内容相同的课程同时在不同的地点进行, 其中, 牛牛预先被安排在教室 ci上课, 而另一节课程在教室 di进行. 在不提交任何申请的情况下,学生们需要按时间段的顺序依次完成所有的n节安排好的课程.如果学生想更换第i节课程的教室,则需要提出中情.若申请通过,学生就可以在第 i个时间段去教室 di上课, 否则仍然在教

【uoj262】 NOIP2016—换教室

http://uoj.ac/problem/262 (题目链接) 题意 有${n}$个时间段,第${i}$个时间段可以选择在${c_i}$教室上课,也可以选择申请换课,有${k_i}$概率申请通过,在${d_i}$上课,另外${1-k_i}$的概率留在${c_i}$教室. 总共有${v}$个教室,${e}$条路径双向联通教室${x_i}$和${y_i}$,路径有权值${w_i}$.在课间时(相邻两个时间段的间隔中),你要从上一个教室走最短路径到下一个教室. 现在你有${m}$次申请机会,只能提前

【题解】NOIP2016换教室

哇好开心啊!写的时候真的全然对于这个加法没有把握,但还是大着胆子试着写了一下--竟然过了样例?于是又调了一下就过啦. 不过想想也觉得是正确的吧,互相独立的事件对于期望的影响自然也是相互独立的,可以把所有的情况看成一个整体,不同的统计方式只是分组的区别,最后算出来的答案肯定是一样的.dp的状态比较显然:dp[i][j][0/1]代表当前在第i节课,已经用去了j次申请的机会,0/1分别代表当前这一节课是否申请.那么这个时候就分情况讨论,计算这一次的选择对于答案的影响. 这些不同的情况分别是:当前和上