换教室

洛咕

题意:有\(n\)个课程,第\(i\)个课程你原本应在\(c_i\)教室上课,同时又有一堂课在\(d_i\)教室,现在你可以提出m个申请,在第i个课程时到\(d_i\)教室上课,成功概率为\(p_i\),给出总共v个教室构成的图,求最小的路径和的期望,\(1≤n≤2000,0≤m≤2000,1≤v≤300\)

分析:设\(f[i][j][0/1]\)表示前\(i\)节课,申请了\(j\)节课换教室,且第i节课申请(1)或者未申请(0)的最小路径期望.最多只有300个教室,首先可以直接\(floyed\)预处理最短路\(dis[x][y]\).设\(c[i]\)表示第\(i\)节课不换教室所在的教室,\(d[i]\)表示第\(i\)节课换教室之后所在的教室,则有,

\(f[i][j][0]=min(f[i-1][j][0]+dis[c[i-1]][c[i]],f[i-1][j][1]+dis[c[i-1]][c[i]]*(1.0-p[i-1])+dis[d[i-1]][c[i]]*p[i-1]*1.0)\)

\(f[i][j][1]=min(f[i-1][j-1][0]+dis[c[i-1]][c[i]]*(1.0-p[i])+dis[c[i-1]][d[i]]*p[i]*1.0,f[i-1][j-1][1]+dis[d[i-1]][d[i]]*p[i]*p[i-1]*1.0+dis[c[i-1]][d[i]]*p[i]*(1.0-p[i-1])+dis[d[i-1]][c[i]]*(1.0-p[i])*p[i-1]+dis[c[i-1]][c[i]]*(1.0-p[i])*(1.0-p[i-1]))\)

//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
inline int read(){
    int s=0,w=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){s=s*10+ch-'0';ch=getchar();}
    return s*w;
}
const int N=2005;
const int M=100005;
int c[N],d[N],dis[305][305];
double p[N],f[N][N][2];
int main(){
    int n=read(),m=read(),v=read(),e=read();
    for(int i=1;i<=n;i++)c[i]=read();
    for(int i=1;i<=n;i++)d[i]=read();
    for(int i=1;i<=n;i++)scanf("%lf",&p[i]);
    for(int i=1;i<=v;i++)
		for(int j=1;j<=v;j++)
	    	dis[i][j]=1e9;
    for(int i=1;i<=v;i++)dis[i][i]=0;
    for(int i=1;i<=e;i++){
		int a=read(),b=read(),c=read();
		if(a!=b)dis[b][a]=dis[a][b]=min(dis[a][b],c);
    }
    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][k]+dis[k][j],dis[i][j]);
    for(int i=0;i<=n;i++)
		for(int j=0;j<=m;j++)
	    	f[i][j][0]=f[i][j][1]=1e9;
    f[1][1][1]=f[1][0][0]=0;
    for(int i=2;i<=n;i++){
		f[i][0][0]=f[i-1][0][0]+dis[c[i]][c[i-1]];
		for(int j=1;j<=i&&j<=m;j++){
	    	f[i][j][0]=min(f[i-1][j][0]+dis[c[i-1]][c[i]],f[i-1][j][1]+dis[c[i-1]][c[i]]*(1.0-p[i-1])+dis[d[i-1]][c[i]]*p[i-1]*1.0);
            	f[i][j][1]=min(f[i-1][j-1][0]+dis[c[i-1]][c[i]]*(1.0-p[i])+dis[c[i-1]][d[i]]*p[i]*1.0,f[i-1][j-1][1]+dis[d[i-1]][d[i]]*p[i]*p[i-1]*1.0+dis[c[i-1]][d[i]]*p[i]*(1.0-p[i-1])+dis[d[i-1]][c[i]]*(1.0-p[i])*p[i-1]+dis[c[i-1]][c[i]]*(1.0-p[i])*(1.0-p[i-1]));
		}
    }
    double ans=1e9;
    for(int i=0;i<=m;i++)
	ans=min(ans,min(f[n][i][0],f[n][i][1]));
    printf("%.2lf\n",ans);
    return 0;
}



posted on 2019-05-07 22:24  PPXppx  阅读(116)  评论(0编辑  收藏  举报