zoukankan      html  css  js  c++  java
  • 【题解】NOIP2016换教室

    哇好开心啊!写的时候真的全然对于这个加法没有把握,但还是大着胆子试着写了一下——竟然过了样例?于是又调了一下就过啦。

    不过想想也觉得是正确的吧,互相独立的事件对于期望的影响自然也是相互独立的,可以把所有的情况看成一个整体,不同的统计方式只是分组的区别,最后算出来的答案肯定是一样的。dp的状态比较显然:dp[i][j][0/1]代表当前在第i节课,已经用去了j次申请的机会,0/1分别代表当前这一节课是否申请。那么这个时候就分情况讨论,计算这一次的选择对于答案的影响。

    这些不同的情况分别是:当前和上一次是否选择申请换课,申请换课的是否成功。

    期望的计算式:成功的概率*成功的代价+失败的概率*失败的代价。

    #include <bits/stdc++.h>
    using namespace std;
    #define maxn 2050
    #define INF 1047483640
    #define maxm 2050
    #define maxv 400
    int n, m, v, e, dis[maxv][maxv], c[maxn], d[maxn];
    double ans = 9999999, dp[maxn][maxm][2], k[maxn];
    
    int read()
    {
        int x = 0, k = 1;
        char c;
        c = getchar();
        while(c < '0' || c > '9') { if(c == '-') k = -1; c = getchar(); }
        while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
        return x * k;
    }
    
    void init()
    {
        for(int i = 1; i <= v; i ++)
            for(int j = i + 1; j <= v; j ++)
                dis[i][j] = dis[j][i] = INF;
        
        for(int i = 1; i <= n; i ++)
            for(int j = 0; j <= m; j ++)
                dp[i][j][0] = dp[i][j][1] = INF;
    }
    
    double gmin(double &x, double y)
    {
        x = (x < y) ? x : y;
    }
    
    int gmin2(int &x, int y)
    {
        x = (x < y) ? x : y;
    }
    
    void Floyd()
    {
        for(int k = 1; k <= v; k ++)
            for(int i = 1; i <= v; i ++)
                for(int j = 1; j <= v; j ++)
                    gmin2(dis[i][j], dis[i][k] + dis[k][j]); 
    }
    
    int main()
    {
        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();
        init(); 
        dp[0][0][0] = dp[0][0][1] = 0;
        for(int i = 1; i <= n; i ++) scanf("%lf", &k[i]);
        for(int i = 1; i <= e; i ++)
        {
            int x = read(), y = read(), z = read();
            dis[x][y] = dis[y][x] = min(dis[y][x], z);
        }
        for(int i = 1; i <= v; i ++) dis[i][i] = 0;
        Floyd();
        for(int i = 1; i <= v; i ++)
            dis[i][0] = dis[0][i] = 0;
        c[0] = d[0] = 0, k[0] = 1;
        for(int i = 1; i <= n; i ++)
            for(int j = 0; j <= m; j ++)
            {
                gmin(dp[i][j][0], dp[i - 1][j][0] + dis[c[i]][c[i - 1]]);
                gmin(dp[i][j][0], dp[i - 1][j][1] + dis[c[i]][c[i - 1]] * (1 - k[i - 1]) + dis[c[i]][d[i - 1]] * k[i - 1]);
                if(j) gmin(dp[i][j][1], dp[i - 1][j - 1][0] + dis[c[i]][c[i - 1]] * (1 - k[i]) + dis[d[i]][c[i - 1]] * k[i]);
                double tem = 0;
                tem += dis[c[i]][c[i - 1]] * (1 - k[i]) * (1 - k[i - 1]);
                tem += dis[c[i]][d[i - 1]] * (1 - k[i]) * k[i - 1];
                tem += dis[d[i]][c[i - 1]] * k[i] * (1 - k[i - 1]);
                tem += dis[d[i]][d[i - 1]] * k[i] * k[i - 1];
                if(j) gmin(dp[i][j][1], dp[i - 1][j - 1][1] + tem);
            }
        for(int i = 0; i <= m; i ++)
            gmin(ans, min(dp[n][i][0], dp[n][i][1]));
        printf("%.2lf", ans);
        return 0;
    }
  • 相关阅读:
    centos shell运行报语法错误: 未预期的文件结尾
    腾讯云防暴力破解防异地登陆
    centos常用命令
    centos7安装nginx
    JavaScript数组倒序函数reverse()
    Ecshop首页购物车数量调取问题
    (原)IPhone开发时把ToolBar中的元素居中的技巧
    iphone开发常用代码笔记
    Windows环境下使用Apache+mod
    [转]C++中sizeof(struct)怎么计算?
  • 原文地址:https://www.cnblogs.com/twilight-sx/p/8456805.html
Copyright © 2011-2022 走看看