CodeForces 883C

题目描述

为了在时间T内下载完f个文件,有三种方案,一种是免费下载,每t0秒下载一个文件。一种是叠加包,花一定的钱然后能够以每t秒下载一个文件,最多能下a个,用完才能切换。叠加包可以无限购买。求最小的花费。

/*
> Problem:CodeForces 883C
> Author: WESTWOOD
> Mail: 965194745@qq.com
> Created Time: 2017/10/23 19:23:16
> function:因为这道题两种流量叠加包要一次性用完所买的流量,所以并没有严格上的优劣可比性。
           题目可以转化为求 f(t0)+f(t1)+f(t2)>=0,满足t0+t1+t2<=T,的情况下cost1+cost2最小
           如果把问题的焦点放在两种叠加包的相互组合的问题上就会很麻烦,无法确定优劣。
           但是免费下载和其中任意一个流量包就有严格的优劣可比性(前提是流量包的下载速度要大过免费下载),
           如果时间分配可以下载完所有文件,那么就能尝试二分减少流量包的使用,
           增加免费下载的文件数量,再次判断,这样能找到最小的花费。
           所以做法就是枚举其中一个流量包的使用,然后二分免费下载和另一个流量包的组合来找最小花费
*/  
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#pragma warning(disable : 4996)
using namespace std;
long long f, T, t0;
long long a[2], t[2], p[2];
int main()
{
    if (fopen("in.txt", "r") != NULL)
    {
        freopen("in.txt", "r", stdin);
        freopen("out.txt", "w", stdout);
    }
    cin >> f >> T >> t0;
    for (int i = 0;i < 2;i++)
        cin >> a[i] >> t[i] >> p[i];
    long long ans = 1e18;
    for (int i = 0;i*t[0] <= T;i++)//枚举的是第一种叠加包
    {
        int rf = f - i, rt = T - i*t[0];//剩余文件数,剩余时间
        int l = 0, r = rf;//二分给另一个叠加包的时间
        if (t[1] >= t0)
        {
            if (i*t[0] + rf*t0 <= T)
                ans = min(ans, (i + a[0] - 1) / a[0] * p[0]);
            continue;
        }
        for (int i = 0;i < 35;i++)
        {
            int m = l + r >> 1;
            if (m*t[1] + (rf - m) *t0 <= rt) r = m;//如果可以下载完就减少叠加包的使用来减少cost,如果流量包的速度更慢这个二分就是错误的
            else l = m;
        }
        if (i%a[0] && r%a[1]) continue;//如果两个包都没用完是非法的
        if (r*t[1] + (rf - r) *t0 > rt) continue;//如果下载时间超出也是非法的
        long long cost = (i + a[0] - 1) / a[0] * p[0] + (r + a[1] - 1) / a[1]*p[1];
        ans = min(ans, cost);
    }
    cout << (ans == 1e18 ? -1 : ans) << '\n';
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值