题目描述
为了在时间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;
}