zoukankan      html  css  js  c++  java
  • 「NOIP 2016」换教室

    Description

    (n) 节课,第 (i) 节课可以选择在教室 (C_i) 上课,也可以选择申请换教室,到教室 (D_i) 上课。若选择申请换课,则有 (K_i) 的概率申请通过,另外 (1-K_i) 的概率依然留在 (C_i) 教室。

    共有 (v) 个教室,(e) 条路径双向连通教室 (X_i)(Y_i),边权为 (W_i)。在每两节课之间,你要从上一个教室走到下一个教室。

    最多提交 (m) 个申请,并且得在第一节课上课之前一次性提交所有申请(也就是,不能根据某一次申请的通过情况来选择下一次申请),要使自己走的路的期望最小。求最优策略下的总距离的期望。

    (1leq nleq 2000,0leq m leq 2000,1leq vleq 300,0leq eleq 9 imes 10^4,1leq W_i leq 1000,0leq K_ileq 1)

    Solution

    考虑 DP,用 (dp_{i,j,0/1}) 表示前 (i) 节课申请了 (j) 次,第 (i) 次是否申请的期望最小值。

    先用 Floyd 预处理出两个教室之间的最短路长度 (dis(i,j))

    (dp_{i,j,0}) 所记录的状态一定处在教室 (c_i)(dp_{i,j,1}) 所记录的状态有 (k_i) 的概率处在 (d_i),另 (1-k_i) 的概率处在 (c_i)

    讨论第 (i) 次是否申请。(P_1,P_2) 是临时变量,分别存第 (i-1) 节课“申请/不申请”两种方案的期望总距离。

    若不申请:

    • (P_1=dp_{i-1,j,0}+dis(c_{i-1},c[i]))
    • (P_2=dp_{i-1,j,1}+k_{i-1} imes dis(d_{i-1},c_i)+(1-k_{i-1}) imes dis(c_{i-1},c_i))

    (dp_{i,j,0}=min(P_1,P_2))

    即在两种策略中选取期望值较小的。

    若申请:

    • (P_1=dp_{i-1,j-1,0}+k_i imes dis(c_{i-1},d_i)+(1-k_i) imes dis(c_{i-1},c_i))
    • (P_2=dp_{i-1,j-1,1}+(1-k_{i-1}) imes k_i imes dis(c_{i-1},d_i)+(1-k_{i-1}) imes (1-k_i) imes dis(c_{i-1},c_i)\+k_{i-1} imes k_i imes dis(d_{i-1},d_i)+k_{i-1} imes (1-k_i) imes dis(d_{i-1},c_i))

    (dp_{i,j,1}=min(P_1,P_2))

    #include<bits/stdc++.h>
    #define int long long
    using namespace std;
    const int N=2010,M=310,inf=1e18;
    int n,m,v,e,c[N],d[N],x,y,z,f[M][M];
    double k[N],dp[N][N][2],p1,p2,ans=inf; 
    signed main(){
        scanf("%lld%lld%lld%lld",&n,&m,&v,&e);
        for(int i=1;i<=n;i++)
            scanf("%lld",&c[i]);
        for(int i=1;i<=n;i++)
            scanf("%lld",&d[i]);
        for(int i=1;i<=n;i++)
            scanf("%lf",&k[i]);
        //初始化两点之间的最短路 
        for(int i=1;i<=v;i++)
            for(int j=1;j<=v;j++)
                f[i][j]=f[j][i]=inf;
        for(int i=1;i<=e;i++){
            scanf("%lld%lld%lld",&x,&y,&z);
            f[x][y]=f[y][x]=min(f[x][y],z); 
        }
        for(int i=1;i<=v;i++)
            for(int j=1;j<=v;j++) f[i][i]=0;
        //floyd 求任意两点之间的最短路 
        for(int k=1;k<=v;k++)
            for(int i=1;i<=v;i++)
                for(int j=1;j<=v;j++)
                    f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
        //初始化期望 
        for(int i=0;i<=n;i++)
            for(int j=0;j<=m;j++)
                dp[i][j][0]=dp[i][j][1]=inf;    //DP 之前的初值概率均为无穷大便于比较
        //DP 计算期望 
        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++){
                p1=dp[i-1][j][0]+f[c[i-1]][c[i]],p2=dp[i-1][j][1]+k[i-1]*f[d[i-1]][c[i]]+(1-k[i-1])*f[c[i-1]][c[i]];
                dp[i][j][0]=min(dp[i][j][0],min(p1,p2));
                if(j){
                    p1=dp[i-1][j-1][0]+k[i]*f[c[i-1]][d[i]]+(1-k[i])*f[c[i-1]][c[i]];
                    p2=dp[i-1][j-1][1]+(1-k[i-1])*k[i]*f[c[i-1]][d[i]]+(1-k[i-1])*(1-k[i])*f[c[i-1]][c[i]]+k[i-1]*k[i]*f[d[i-1]][d[i]]+k[i-1]*(1-k[i])*f[d[i-1]][c[i]];
                    dp[i][j][1]=min(dp[i][j][1],min(p1,p2));
                } 
            }
        //计算答案 
        for(int i=0;i<=m;i++)
            ans=min(ans,min(dp[n][i][0],dp[n][i][1]));
        printf("%.2lf
    ",ans);
        return 0;
    } 
  • 相关阅读:
    Atitit 华为基本法 attilax读后感
    Atitit 华为管理者内训书系 以奋斗者为本 华为公司人力资源管理纲要 attilax读后感
    Atitit 项目版本管理gitflow 与 Forking的对比与使用
    Atitit 管理的模式扁平化管理 金字塔 直线型管理 垂直管理 水平管理 矩阵式管理 网状式样管理 多头管理 双头管理
    Atitit 乌合之众读后感attilax总结 与读后感结构规范总结
    深入理解 JavaScript 异步系列(4)—— Generator
    深入理解 JavaScript 异步系列(3)—— ES6 中的 Promise
    深入理解 JavaScript 异步系列(2)—— jquery的解决方案
    深入理解 JavaScript 异步系列(1)——基础
    使用 github + jekyll 搭建个人博客
  • 原文地址:https://www.cnblogs.com/maoyiting/p/13454610.html
Copyright © 2011-2022 走看看