• poj3231


    简单模拟,题意描述不清晰,我来仔细描述一下,flashget在下载一些文件,每个文件有一个初始大小,初始速度,最大速度。当一个文件下载结束后,他的速度(占用的带宽)会平均分配给别的任务(各文件的速度增加值相同),假设我们要把速度x分配给a个文件,那么就要给每个文件分配x/a的速度,前提条件是分配后该文件的速度不超过其最大速度。若超过了则不能给他分配这么多,只让它达到其最大速度即可。这样一来我们的下载速度就会有剩余,因为受到最大速度的限制,有些文件并没有被分配到x/a这么多的速度。对于剩余的速度怎么处理呢?就是除去那几个已经到达最大速度的文件,其余文件按照刚才的方法再分配一次剩余速度。模拟即可。这题精度很难控制,我开始试着用先将所有到达最大速度的进程先处理,最后再计算平均值的方法,居然是错的,理论上这种做法比上述做法精度高。

    View Code
    #include <iostream>
    #include <cstdlib>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    #define maxn 105
    
    struct Elem
    {
        double size, speed, max_speed;
    } elem[maxn];
    
    int n, m;
    double time_left[maxn];
    bool finished[maxn];
    double ans[maxn];
    double reached[maxn];
    int task_left;
    
    void input()
    {
        scanf("%d", &m);
        for (int i = 0; i < n; i++)
            scanf("%lf%lf%lf", &elem[i].size, &elem[i].speed, &elem[i].max_speed);
    }
    
    void cal_time()
    {
        for (int i = 0; i < n; i++)
            if (!finished[i])
                time_left[i] = elem[i].size / elem[i].speed;
    }
    
    void size_reduce(double min_time)
    {
        for (int i = 0; i < n; i++)
            if (!finished[i])
                elem[i].size -= min_time * elem[i].speed;
    }
    
    int get_min()
    {
        int ret = 0;
        while (finished[ret])
            ret++;
        for (int i = ret + 1; i < n; i++)
            if (!finished[i] && time_left[i] < time_left[ret])
                ret = i;
        return ret;
    }
    
    void distribute(double bandwidth)
    {
        double band_left = bandwidth;
        int num = 0;
        for (int i = 0; i < n; i++)
            if (!finished[i] && !reached[i])
                num++;
        if (num == 0)
            return;
        double average;
        while (band_left > 0)
        {
            average = band_left / num;
            bool did = false;
            for (int i = 0; i < n; i++)
            {
                if (finished[i] || reached[i])
                    continue;
                did = true;
                if (elem[i].max_speed - elem[i].speed < average)
                {
                    band_left -= elem[i].max_speed - elem[i].speed;
                    elem[i].speed = elem[i].max_speed;
                    reached[i] = true;
                    num--;
                }else
                {
                    band_left -= average;
                    elem[i].speed += average;
                }
            }
            if (!did)
                break;
        }
    }
    
    void work()
    {
        memset(finished, 0, sizeof(finished));
        memset(reached, 0, sizeof(reached));
        double now_time = 0;
        task_left = n;
        while (task_left > 0)
        {
            cal_time();
            int next_task = get_min();
            finished[next_task] = true;
            task_left--;
            double bandwidth = elem[next_task].speed;
            double min_time = time_left[next_task];
            size_reduce(min_time);
            now_time += min_time;
            ans[next_task] = now_time;
            distribute(bandwidth);
        }
    }
    
    int main()
    {
        //freopen("t.txt", "r", stdin);
        int t = 0;
        while (scanf("%d", &n), n)
        {
            t++;
            printf("Case %d:\n", t);
            input();
            work();
            for (int i = 0; i < n; i++)
                printf("NO%d:%.3fs\n", i + 1, ans[i]);
        }
        return 0;
    }
  • 相关阅读:
    docker中centos7安装ssh服务
    redis加入systemctl服务
    elasticsearch设置执行脚本并添加开机启动 (转)
    CentOS7使用firewalld打开关闭防火墙与端口
    腾讯地图JSAPI开发demo 定位,查询
    C# 开发AliYun(阿里云) 小蜜调用接口代码
    VSCode 开发Core教程
    Rabbit原理理解
    Exceptionless 本地部署
    Visual Studio 2019 自带混淆工具DotFuscator不需要去网络下载
  • 原文地址:https://www.cnblogs.com/rainydays/p/2750060.html
Copyright © 2020-2023  润新知