P1850 换教室 题解

题目链接:-----

题意:

有 v 间教室, 教室之间有 e 条双向边连接, 从一个教室走到另一个教室需要一
定时间. 有 n 节课, 第 i 节课有两间教室, 默认要去第 c[i] 间教室, 可以申请到
第 d[i] 间教室去, 申请通过的概率为 p[i], 所有申请必须在最开始提交. 求出提
交申请个数不超过 m 的情况下, 依次上完这 n 节课期望最少要走多远.
v ≤ 300, e ≤ 90000, n ≤ 2000.

前置知识:

1.全概率公式:

P(A)=sum_{i=1}^{n} {P(A|Bi)*P(Bi)}

2.随机变量是在概率空间的基本变量上定义的函数.
记 E(X) 为随机变量 X 的期望值

E(X)=sum_{w=1}^{n} {P(w)*X(w)}

可以看做概率乘以权值。

3.期望具有线性性:

E(aX + Y ) = aE(X) + E(Y )

题解思路:

每节课之间要走的路程的期望之和可以根据期望的线性性,

求出每一个路程的期望,累加即可。

1.先用floyd求出最短路。

2.f[i][j][0/1]表示上完第I节课后,用了j次申请,第i节课是否换教室,期望路程的最小值。

3.因为它只是期望,如果有期望得到申请,也得加上期望没有得到申请的情况。

4.转移方程比较恶心,我就不贴了。

代码:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<queue>
#define ll long long 
#define R register
using namespace std;
const int N=2005;
const int M=2005;
const int INF=200000000;
//14299.96
//f[i][j][0/1]  到第i节课  用了 j 个 申请 第i节课换不换的期望
int n,m,v,e,c[N],d[N],far[M][M];
double f[N][N][2],k[N],ans=INF;
int main(){
    scanf("%d%d%d%d",&n,&m,&v,&e);//时间 次数 点数 边数
    for(R int i=1;i<=n;i++)
    scanf("%d",&c[i]);//不换
    for(R int i=1;i<=n;i++)
    scanf("%d",&d[i]);//
    for(R int i=1;i<=n;i++)
    scanf("%lf",&k[i]);//概率

    for(R int i=1;i<=v;i++)
    for(R int j=1;j<=v;j++)
    far[i][j]=INF;
    for(R int i=1;i<=e;i++)
    {
        R int u,v;
        R int w;
        scanf("%d%d%d",&u,&v,&w);
        far[u][v]=min(w,far[u][v]);
        far[v][u]=min(w,far[v][u]);
    }

    for(R int i=1;i<=v;i++)
    far[i][i]=0;

    for(R int t=1;t<=v;t++)
    for(R int i=1;i<=v;i++)
    for(R int j=1;j<=v;j++)
    far[i][j]=min(far[i][j],far[i][t]+far[t][j]);

    for(R int i=1;i<=n;i++)
    for(R int j=0;j<=m;j++)
    for(R int t=0;t<=1;t++)
    f[i][j][t]=INF;
    
    f[1][0][0]=0;
    f[1][1][1]=0;
    for(R int i=2;i<=n;i++)
    {
        for(R int j=0;j<=min(m,i);j++)
        {
        if(j<=i-1)
        f[i][j][0]=min(
        f[i-1][j][0]+
        far[c[i-1]][c[i]],
        
        f[i-1][j][1]+
        far[d[i-1]][c[i]]*k[i-1]+
        far[c[i-1]][c[i]]*(1-k[i-1]));
        
        if(j!=0)
        f[i][j][1]=min(
        f[i-1][j-1][0]+
        far[c[i-1]][d[i]]*k[i]+
        far[c[i-1]][c[i]]*(1-k[i]),
        
        f[i-1][j-1][1]+
        far[d[i-1]][d[i]]*k[i]*k[i-1]+
        far[c[i-1]][d[i]]*(1-k[i-1])*k[i]+
        far[d[i-1]][c[i]]*(1-k[i])*k[i-1]+
        far[c[i-1]][c[i]]*(1-k[i])*(1-k[i-1]));
        }
    }
    for(R int i=0;i<=m;i++){
        if(i<=n-1)
        ans=min(ans,f[n][i][0]);
        if(i!=0)
        ans=min(ans,f[n][i][1]);
    }
    printf("%.2lf",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/sky-zxz/p/9882481.html