zoukankan      html  css  js  c++  java
  • P1850 换教室[dp+期望]

    流下了不会概率的眼泪,由于不会概率,转移少写了点东西。。。

    这个dp很简单,就是一个普通的线性dp加点期望。(刚开始写这道题时信笔写下)

    (dp[0/1][i][j])表示到第(i)个时间段时,已经申请了换(j)门课程的教室,当前申请0不换、1换教室的最小数学期望。

    注意,我们的状态定义是申请,而不是已经申请成功,这样定义状态就可以统计出数学期望了。

    对于当前状态没申请的情况,如果上一个时间段也没申请,那只有一种可能性发生,即俩状态都没换;如果上一个时间段申请了,那上一个状态就可能没成功,也可能成功了,二者我们都要统计。

    对于申请了的情况也是一样的。

    故有转移(巨长版)

    [dp[0][i][j]=min(dp[0][i-1][j]+dist(c_{i-1},c_{i}),\dp[1][i-1][j]+k_{i-1}*dist(d_{i-1},c_i)+(1-k_{i-1})*dist(c_{i-1},c_i))\~\dp[1][i][j]=min(dp[0][i-1][j-1]+k_i*dist(c_{i-1},d_i)+(1-k_i)*dis(c_{i-1},c_i),\dp[1][i-1][j-1]+k_{i-1}*k_i*dist(d_{i-1},d_i)+(1-k_{i-1})*k_i*dist(c_{i-1},d_i)+k_{i-1}*(1-k_i)*dist(d_{i-1},c_i)+(1-k_{i-1})*(1-k_i)*dist(c_{i-1},c_i)) ]

    其中(dist(x,y))表示最短路,观察数据范围,点数较少,直接上floyd。

    初始化(dp[0][1][0]=dp[1][1][1]=0,dp[0/1][][]=inf)

    答案在(min(dp[0/1][n][0sim m]))

    注意重边和I(inf) 的设置,不要搞混(n)(v)

    参考代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<string>
    #include<cstdlib>
    #include<queue>
    #include<vector>
    #define INF 0x3f3f3f3f
    #define PI acos(-1.0)
    #define N 310
    #define M 2010
    #define MOD 2520
    #define E 1e-12
    #define eps 4e-4
    #define re register
    using namespace std;
    inline int read()
    {
    	int f=1,x=0;char c=getchar();
    	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    	while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    	return x*f;
    }
    int n,m,v,e,c[M],d[M],dis[N][N];
    double k[M],dp[2][M][M];
    inline int Min(int a,int b){return a<b?a:b;}
    inline double dmin(double a,double b){return a-b<eps?a:b;}//卡常(
    inline void init()
    {
    	for(re int k=1;k<=v;++k)
    		for(re int i=1;i<=v;++i)
    			for(re int j=1;j<=v;++j)
    				dis[i][j]=Min(dis[i][j],dis[i][k]+dis[k][j]);//floyd
    	for(re int i=1;i<=v;++i) dis[i][i]=dis[0][i]=dis[i][0]=0;//仔细观察,这也是dp边界的一部分
    	for(re int i=0;i<=n;++i)
    		for(re int j=0;j<=m;++j) dp[0][i][j]=dp[1][i][j]=INF*1.0;
    }
    int main()
    {
    	n=read(),m=read(),v=read(),e=read();
    	memset(dis,0x3,sizeof(dis));
    	for(re int i=1;i<=n;++i) c[i]=read();
    	for(re int i=1;i<=n;++i) d[i]=read();
    	for(re int i=1;i<=n;++i) scanf("%lf",&k[i]);
    	for(re int i=1;i<=e;++i){
    		int u=read(),v=read(),w=read();
    		dis[u][v]=dis[v][u]=Min(dis[u][v],w);
    	}
    	init();
    	dp[0][1][0]=dp[1][1][1]=0;
    	for(re int i=2;i<=n;++i)
    		for(re int j=0;j<=Min(i,m);++j){
    			dp[0][i][j]=dmin(dp[0][i-1][j]+dis[c[i-1]][c[i]],dp[1][i-1][j]+k[i-1]*dis[d[i-1]][c[i]]+(1-k[i-1])*dis[c[i-1]][c[i]]);
    			if(j>=1) dp[1][i][j]=dmin(dp[0][i-1][j-1]+k[i]*dis[c[i-1]][d[i]]+(1-k[i])*dis[c[i-1]][c[i]],dp[1][i-1][j-1]+k[i]*k[i-1]*dis[d[i-1]][d[i]]+k[i]*(1-k[i-1])*dis[c[i-1]][d[i]]+(1-k[i])*k[i-1]*dis[d[i-1]][c[i]]+(1-k[i])*(1-k[i-1])*dis[c[i-1]][c[i]]);
    		}
    	double ans=INF*1.0;
    	for(re int i=0;i<=m;++i)
    		ans=dmin(ans,dmin(dp[0][n][i],dp[1][n][i]));
    	printf("%.2lf",ans);
    	return 0;
    }
    
  • 相关阅读:
    redis集群搭建
    redis状态查看
    redis动态修改参数配置
    redis的info
    redis安装配置
    redis命令总结
    rabbitmq安装
    怎么把U盘启动改为硬盘启动(适用于U盘安装系统时)
    监控宝篇之一(快速入门)
    raid详解
  • 原文地址:https://www.cnblogs.com/DarkValkyrie/p/11837932.html
Copyright © 2011-2022 走看看