Simple Distributed storage system 【POJ - 3757】【WA到自闭竟然是因为这个原因!讲解01分数规划】

46 篇文章 0 订阅

题目链接


Description

Jack helps his mentor build a simple distributed storage system. He uses several servers and connects them as the following topology:

This distributed storage system contains a group of backend servers and a master server. The backend servers are different from each other while they store identical data, and all of them are invisible to client. When a client machine needs a file, it sends request to a master server. The master server collects different part of the file from some of backend servers. The strategy of the master is like follows.

Each backend server has its own processing throughput and transmission bandwidth. The master server knows that ith backend server’s throughput is pi (MB/s) and bandwidth is bi (MB/s). As the result, omitted the propagation time, handling size of fi MB data and sending to master machine needs time:

Total time = Processing time + Transmission time = fi / pi + fi / bi

In addition, handling 1 MB data on ith server costs ci. (Including electricity consumption and maintenance cost, etc.) In order to minimize the total cost, the master server should carefully decide which backends should be used and how much load they should process. At the same time, because of some consistency consideration, every time the master should choose exactly K backend servers to extract file, and each of them should take exactly the same time to finish the job.

Your task is to write a scheduling program for the master server. Assuming the size of the file is F MB, and the file can be infinitely divided.

Input

The first line contains two integers N and K (K≤ N ≤ 20000), and a real number F. The master should choose exactly K machines among total N backend servers. The F is the size of the file.

The following N lines describe the details of each backend servers. Each line contains three real numbers, pi, bi and ci, representing the processing throughput, bandwidth and unit cost.

Output

The output file contains only one real number, the minimum cost. The answer is less than 10000000000 and should be rounded to four digits

Sample Input

3 2 2
1 1 2
1 1 1
2 2 10

Sample Output

3.0000

Hint

In the sample case, the master should choose the first two backend machines. Each of them should handle 1 MB part of the file (total is 2 MB) in order to make the finishing time identically (2 second). The total cost is 1*2+1*1 = 3.0000


  这道题来来回回WA了20次了,然后才想起来POJ比较的老了,输出printf("%.4lf")是会返回WA的,WA到自闭才有这样的灵光一现…… 然后在测,就不会WA的那么快了,1A!!!简直了啊!

  前面部分就是很基础的01分数规划,找最优解问题,但是一开始的时候以为是线性的,直接二分了时间time是显然错误的。

推理一下:

fi = ti * vi

fi * (1 / pi + 1/bi) = ti

vi = pi * bi / (pi + bi)  这里的vi指的是每个电脑处理所花费的时间;

fi = vi * ti

又有对于全体的ti,是相等的,则另ti = t;

cost(i) = fi * ci = vi * ti * ci = vi * t * ci

cost = \sum cost(i) = \sum (vi * ci) * t

不妨令 xi = vi * ci

则有cost = \sum xi * t

根据fi = vi * t,我们可以知道t = fi / vi

我们想用01分数规划去寻找答案的话,过程中就会是一个毕竟的过程,那么,就会使得F \leq \sum fi = t * \sum vi

则会有t \geq F / \sum vi

cost = \sum xi * t \geq \sum xi * F / \sum vi = F * \sum xi / \sum vi

相当于是:

cost * \sum vi - F * \sum xi \geq 0

最优解情况当然是" ==0 "情况啊!

然后我们就对上面这个式子去进行01分数规划,二分答案cost即可!!!

千万注意,不要输出"%.4lf",强调用"%.4f"!!!

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define efs 1e-6
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
using namespace std;
typedef double lb;
typedef unsigned long long ull;
typedef long long ll;
const int maxN = 2e4 + 7;
int N, K;
lb F;
lb l = 0., r = 10000000000., mid = 0., ans = 0.;
struct node
{
    lb p, b, c;
    node(lb _p = 0, lb _b = 0., lb _c = 0.):p(_p), b(_b), c(_c) {}
    lb vi;
    void doit() { vi = p * b / (p + b); }
}a[maxN];
bool cmp(node e1, node e2) { return mid * e1.vi - F * e1.vi * e1.c > mid * e2.vi - F * e2.vi * e2.c; }
int main()
{
    scanf("%d%d%lf", &N, &K, &F);
    for(int i=1; i<=N; i++) { scanf("%lf%lf%lf", &a[i].p, &a[i].b, &a[i].c); a[i].doit(); }
    l = 0.; r = 10000000000.; mid = 0.; ans = 10000000000.;
    lb sum;
    while(r - l >= efs)
    {
        mid = (l + r) / 2.;
        sort(a + 1, a + N + 1, cmp);
        sum = 0.;
        for(int i=1; i<=K; i++) sum += mid * a[i].vi - F * a[i].vi * a[i].c;
        if(sum >= 0)
        {
            r = mid;
            ans = mid;
        }
        else l = mid;
    }
    printf("%.4f\n", ans);
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wuliwuliii

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值