传输方案规划问题

这就是astar比赛时当初失误把List[i][j]下标写反了的那个题目,很可惜 这个问题的原理可以用这个数学不等式表示,那就是 a,b,c,d均为正整数,那么由 a/b > c/d 可以推出 a/b > (a+c)/(b+d) > c/d 传输方案规划 (30分) 问题背景 面对艰巨复杂的技术挑战,百度所崇尚的系统设计哲学是“简单可依赖”,而百度的工程师们正在互联网世界中实践着这种理念。这里正好有一个挑战,让作为百度之星的你小试牛刀: 在处理数以百亿计的网络信息的过程中,有一个很常见的问题: 怎么样将一个集群上的信息以最低的成本传输到另外一个集群上?     * 数据源集群A有n台服务器,编号为 1, 2, ..., n,i号服务器上待传输的数据量为Ai ,单位是GB。     * 目的地集群B有m台服务器,编号为 1, 2, ..., m,j号服务器上的空闲容量为 Bj,单位为 GB。     * A集群的i号服务器上的每GB数据对于B的集群的j号服务器收益为Vi,j,从 A 集群的 i 号服务器向 B 集群的 j 号服务器传输 1GB数据的开销为Ci,j。 你的任务是在保证A中的所有数据传输完毕的前提下,性价比V/C尽量高。其中V为所有数据在B集群上的价值之和,C为总开销。换句话说,若A集群的i号服务器向B集群的j号服务器发送了Ti,j个GB的数据(Ti,j不一定是整数),则性价比定义为: 输入格式 第1行两个整数n, m(1<=n,m<=50),即集群A和B各自的服务器台数。 第2行包含n个不超过100的正整数A1,A2,…,An,即集群A中每台服务器的待传输数据量(单位:GB)。 第3行包含m个不超过100的正整数B1,B2,…,Bm,即集群B中每台服务器所能接受的最大数据量(单位:GB)。 第 4 ~ n+3 行每行包含m个不超过100的非负整数Vi,j,表示集群A的i号服务器中每GB数据对于集群B中的j号服务器的价值。 第 n+4 ~ 2n+3 行每行包含m个不超过100的正整数Ci,j,表示集群A的i号服务器中每GB数据传输到集群B中的j号服务器所需要的开销。 输出格式 仅一行,为最大性价比。输出保留三位小数(四舍五入)。如果A的数据无法传输完毕,输出字符串 “-1”(无引号)。 样例输入 2 2 1 2 2 1 11 0 7 5 6 1 3 2 样例输出 2.091 样例解释 一个方案是: 集群A的1号服务器把所有数据传输到集群B的1号服务器,价值11,开销6。 集群A的2号服务器把1GB数据传输到集群B的1号服务器,价值7,开销3,然后把剩下的1GB数据传输到集群B的2号服务器,价值5,开销2。 性价比:(11+7+5)/(6+3+2)=2.091 另一个方案是: 集群A的1号服务器把所有数据传输到集群B的2号服务器,价值0,开销1。 集群A的2号服务器把所有数据传输到集群B的1号服务器,价值14,开销6。 性价比:(0+14)/(1+6)=2。 第一种方案更优。
#include <iostream>

#include <cstdio>



using namespace std;



// A,B 群台数

int N;

int M; 



// A,B 群各机器容量

int A_CON[51];

int B_CON[51];



// 总收益,总开销

int totalV; 

int totalC; 



// 

int totaltransferGB;



pair<int, int> List[51][51];



void transfer_onetime()

{

    int i,j;

    float vc;

    float maxvc = 0;

    int maxvcAi, maxvcBj;

    int found = 0;

    for (i = 1; i <= N  ; i++)

    {

        if (found) break;

        if (A_CON[i] == 0) continue;

        for (j = 1; j <= M ; j++)

        {

            if (B_CON[j] == 0) continue;

            // 如果开销为0则为最大传输

            if (List[i][j].second == 0)

            {

                maxvcAi = i;

                maxvcBj = j;

                found = 1;

                break;

            }

            vc = (float)List[i][j].first/(float)List[i][j].second;

            if (vc >= maxvc)

            {

                maxvc = vc;

                maxvcAi = i;

                maxvcBj = j;

            }

        }

    }



    // 

    int transferGB = A_CON[maxvcAi]>B_CON[maxvcBj]?B_CON[maxvcBj]:A_CON[maxvcAi];



    A_CON[maxvcAi] -= transferGB;

    B_CON[maxvcBj] -= transferGB;

    totalV += transferGB * List[maxvcAi][maxvcBj].first;

    totalC += transferGB * List[maxvcAi][maxvcBj].second;

    totaltransferGB += transferGB;

}



int main2(int argc, int argv[])

{

    freopen("t3.in", "r", stdin);

    scanf("%d%d", &N, &M);



    // 集群A中每台服务器的待传输数据量

    int i = 1;

    while( i <= N )

    {

        scanf("%d", &A_CON[i]);

        i++;

    }



    // 集群B中每台服务器所能接受的最大数据量

    i = 1;

    while( i <= M )

    {

        scanf("%d", &B_CON[i]);

        i++;

    }



    // 集群A的i号服务器中每GB数据对于集群B中的j号服务器的价值

    int j;

    for (i = 1; i <= N  ; i++)

        for (j = 1; j <= M ; j++)

            scanf("%d", &List[i][j].first);



    // 集群A的i号服务器中每GB数据传输到集群B中的j号服务器所需要的开销

    for (i = 1; i <= N  ; i++)

        for (j = 1; j <= M ; j++)

            scanf("%d", &List[i][j].second);



    

    // 判断是否可以可以传输完毕

    int totalA = 0;

    int totalB = 0;

    for (i = 1 ; i <= N; i++)

        totalA += A_CON[i];

    for (i = 1 ; i <= N; i++)

        totalB += B_CON[i];

    if (totalA > totalB)

    {

        printf("-1/n");

        return 0;

    }



    totalV = 0;

    totalC = 0;

    totaltransferGB = 0;



    // 每轮传输一次最大VC的数据

    while (totaltransferGB < totalA)

    {

        transfer_onetime();

    }



    printf("%0.3f/n", (float)totalV/(float)totalC);

    return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值