加载中…
个人资料
JosiahChiu
JosiahChiu
  • 博客等级:
  • 博客积分:0
  • 博客访问:7,096
  • 关注人气:87
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

POJ PKU 3757 二分 模拟

(2010-04-08 15:41:24)
标签:

poj

pku

3757

it

分类: 杂题

题目描述:

你需要从k台电脑共同下载一个大小为F的东西(就是今天的BT),这k台中每台要下的大小为fi,

则易知, 需要满足k个fi的和恰为F,而且第i台电脑的下载所需时间

t = fi / pi fi / bi ,其中pi和bi是给定的参数,要求这k台的t都要相同,保证下载同步。

每天电脑的下载花费为fi * ci。

现在给你n台电脑,每台电脑有参数pi,bi,ci还有下载东西的总大小F,让你从中选k台下载,问你最小的花费是多少。

 

解题:

容易知道,每台电脑的下载速度vi * t = fi  立即得: vi = (pi * bi) / (pi bi),假设选了k台,则总速度为sigema(vi) 0 < i < k  sigema为求和符号。

每台电脑需要的时间(也是总时间,因为要同步) 为 t = F / sigema(vi);

总花费为 sigema(vi * fi) = sigema(t * vi * ci).  其中t * vi = fi

设xi = vi * ci

总花费即为: cost = F * (x0 x1 ... xk-1) / (v0 v1 ... vk-1),F为定值

把右边的分母乘到左边,即设 y = sigema(cost * vi - F * xi) = 0

二分枚举cost,对于每个cost,把0~n台电脑的cost * vi - F * xi排序,去最小的前k个,求和得y,

如果y > 0 cost 偏大,否则偏小,符合二分策略。

代码如下:

#include<iostream>
#include<cmath>
#include<cstdio>
#include<algorithm>
#define epx 0.000001
using namespace std;
int n, k;
double f, l, r, mid;
struct e
{
    double p, b, c;
}x[20004];
bool cmp(e a, e b)
{
    return a.b < b.b;
}
double aabs(double a){    if(a>0)   return a;    else   return -a;}
int main()
{
    scanf("%d%d%lf", &n, &k, &f);
    for(int i = 0; i < n; i )
    {
        scanf("%lf%lf%lf", &x[i].p, &x[i].b, &x[i].c);
        x[i].p = (x[i].p * x[i].b) / (x[i].p x[i].b);
    }
    l = -1, r = 100000000000LL;
    while(aabs(r - l) > epx)
    {
        mid = (l r) / 2;
        for(int i = 0; i < n; i )
            x[i].b = x[i].p * (x[i].c - mid / f);
        sort(x, x n, cmp);
        double sum = 0;
        for(int i = 0; i < k; i )
            sum = x[i].b;
        if (sum >= 0)
            l = mid;
        else
            r = mid;
    }
    printf("%.4f\n", mid);
    return 0;
}

0

阅读 收藏 喜欢 打印举报/Report
前一篇:2010-04-07
后一篇:2010-04-08
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有