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

    为什么我觉得这年D1非常之丧……

    题目链接

    看到题目有点晕……,反正发现v<=500之后先写了floyd,不写白不写。

    现在我们有任意两点之间的最短路了,考虑dp(i表示考虑到第i个时间段)

    f[i][j][0]=min(跑到c[i]的期望距离)

    f[i][j][1]表示min(跑到c[i]的期望距离*(1-k[i])+跑到d[i]的期望距离*k[i] )(即假设在i交了申请跑到第i个教室的最短期望距离)

    什么意思呢?

    先设 g[x] = 跑到x的期望距离

    我们假设有 i 要从 i-1 转移。

    假若i-1处不交转课申请,无论对于d[i]还是c[i] 我们肯定希望 g[c[i-1]] 越小越好。

    假若i-1处交了转课申请,同理

    我们肯定希望 (g[c[i-1]]+dis[c[i-1]][c[i]])*(1-k[i-1])+(g[d[i-1]]+dis[d[i-1]][c[i]])*k[i-1] 以及

           (g[c[i-1]]+dis[c[i-1]][d[i]])*(1-k[i-1])+(g[d[i-1]]+dis[d[i-1]][d[i]])*k[i-1]越小越好。

    发现dis其实无法改变,考虑把dis删去,得到g[c[i-1]]*(1-k[i-1])+g[d[i-1]]*k[i-1],我们要最小化的是它。

    这时我们发现一个dp[i][j]其实需要维护两个状态才能满足最优子结构的性质。

    因此就有了上面的状态表示,我们考虑n^2转移即可,转移方程不难想,但是很难写……

    代码(式子巨长,细节巨多,心力交瘁):

    #include<cstdio>
    #include<cstring>
    #define min(a,b) (a<b?a:b)
    #define init(x,p) memset(x,p,sizeof(x))
    int map[505][505];
    int n,m,v,e,c[2005],d[2005];
    double k[2005],dp[2005][2005][4];
    void init_dp();
    void floyd();
    int main(){
    //    freopen("xx.txt","r",stdin);
        init(map,0x3f);
        scanf("%d%d%d%d",&n,&m,&v,&e);
        for(int i=1;i<=n;++i){
            scanf("%d",&c[i]);
            if(c[i]==0) return -1;
        }
        for(int i=1;i<=n;++i) scanf("%d",&d[i]);
        for(int i=1;i<=n;++i) scanf("%lf",&k[i]);
        for(int i=1;i<=e;++i){
            int a,b,cd;
            scanf("%d%d%d",&a,&b,&cd);
            map[a][b]=map[b][a]=min(map[b][a],cd);
        }
        for(int i=1;i<=v;++i) map[i][i]=0;
        floyd();
        init_dp();
        dp[1][0][0]=dp[1][0][1]=0;
        #define f map
        for(int i=2;i<=n;++i){
            for(int j=0;j<=min(n,m);++j){
                if(!j){
                    dp[i][j][0]=dp[i-1][j][0]+f[c[i-1]][c[i]];
                    dp[i][j][1]=f[c[i-1]][c[i]]*(1-k[i])+f[c[i-1]][d[i]]*k[i]+dp[i-1][j][0];
                    continue;
                }
                dp[i][j][0]=min(
                    dp[i-1][j][0]+f[c[i-1]][c[i]],
                    dp[i-1][j-1][1]+f[d[i-1]][c[i]]*(k[i-1])+f[c[i-1]][c[i]]*(1-k[i-1])
                );
                dp[i][j][1]=min(
                    f[c[i-1]][c[i]]*(1-k[i])+f[c[i-1]][d[i]]*k[i]+dp[i-1][j][0],
                    (f[d[i-1]][c[i]]*(k[i-1])+f[c[i-1]][c[i]]*(1-k[i-1]))*(1-k[i])+(f[d[i-1]][d[i]]*(k[i-1])+f[c[i-1]][d[i]]*(1-k[i-1]))*k[i]+dp[i-1][j-1][1]
                );
            }
        }
        #undef f
    //    printf("%.3f",min(f[n][j][]))
        double ans=1e10;
        for(int j=0;j<=m;++j){
            ans=min(ans,dp[n][j][0]);
            if(j!=m) ans=min(ans,dp[n][j][1]);
        }
        printf("%.2lf
    ",ans);
        return 0;
    }
    
    void floyd(){
        for(int k=1;k<=v;++k)
            for(int i=1;i<=v;++i)
                for(int j=1;j<=v;++j)
                    map[i][j]=min(map[i][k]+map[k][j],map[i][j]);
        return ;
    }
    
    void init_dp(){
        for(int i=0;i<2005;++i)
            for(int j=0;j<2005;++j)
                dp[i][j][0]=dp[i][j][1]=1e8;
    }
    丑代码
  • 相关阅读:
    [LOJ537] DNA 序列
    yum安装jdk
    centos7添加tomcat自启服务
    ajax下载文件的方法 php下载图片的方法
    kali linux dpkg安装和删除的方法
    javascript 曲线流光动画
    javascript获取曲线路径每个像素的坐标
    抓取微信小程序源码的方法
    javascript canvas拖尾效果
    php错误execution timed out (118.236064 sec), terminating解决方法
  • 原文地址:https://www.cnblogs.com/JiuPleber/p/9893382.html
Copyright © 2011-2022 走看看