poj1018

题目描述:有一批订单(order),需要n种设备组成一个交流系统。每种设备有m个设备制造商,每个设备制造商的设备都有不同的带宽(bandwidth)和价格(price)。
定义系统的带宽(B)为这个n个设备里面的最小带宽
定义系统的价格(P)为n个设备的总价格
现在要求你设计程序计算从设备制造商提供的所有设备中选出n个(每种一个)使得系统的B/P最大
输入格式:第一行一个整数t,表示总共有t组数据。以下每组数据第一行一个整数n,表示设备的种类,以下n行每行开头一个整数m(i)表示第i种类的设备制造商的数量。 m(i)后面接着m(i)对整数,每对整数表示这m(i)个设备的带宽和价格。
输出格式:每组数据输出一行一个小数,表示最大的B/P
数据约定:1<=n,m<=100
解题思路:贪心枚举
将所有设备以价格为关键字从小到大排序。然后依次枚举每个设备i,把当前设备i 的带宽当做系统的最小带宽,计算B/P,取所有B/P中的最大值。。这里可以加上一些优化。。
妈蛋的WA了7次。。因为快排写萎了。。。郁闷到死!!!
更详细的看代码注释。PS:第一次写代码注释。。。

#include <cstdio>

struct _dev{
    int price;
    int bandwith;
};

void sort(_dev *head, _dev *tail);

int main(int argc, char const *argv[])
{
    int t;
    scanf("%d", &t);
    while(t--){
        int n, m[111];
        scanf("%d", &n);
        _dev dev[111][111];
        for(int i=0; i<n; ++i){
            scanf("%d", m+i);
            for(int j=0; j<m[i]; ++j){
                scanf("%d%d", &dev[i][j].bandwith, &dev[i][j].price);
            }
            sort(dev[i],dev[i]+m[i]-1);
        }
        double ans=0;
        for(int i=0; i<n; ++i){
            for(int j=0; j<m[i]; ++j){  //两重循环保证每一个设备都被枚举到
                //以当前设备的带宽为最小带宽,初始化此次系统构成方案
                int minbandwith=dev[i][j].bandwith;
                int sumprice=dev[i][j].price, k, r;
                for(k=0; k<n; ++k){
                    if(k==i) { continue; } //当前设备所在的种类直接不考虑
                    for(r=0; r<m[k]; ++r){
                        //判断设备的带宽是否满足要求,满足要求,则选择这个设备,
                        //因为按照价格排了顺序,所以第一个满足要求的设备价格一定最小,
                        if(minbandwith<=dev[k][r].bandwith) {
                            sumprice += dev[k][r].price;
                            break;
                        }
                    }
                    //如果第k中设备里找不到符合要求的设备
                    //说明当前带宽的系统无法被构成,跳过该方案
                    if(r==m[k]){ break; }
                }
                //判断设备数量是否达到要求,数量不够,说明系统无法构成
                if(k<n) { continue; }
                //数量达到要求,更新结果。
                if(minbandwith/(double)sumprice>ans) {
                    ans=minbandwith/(double)sumprice;
                }
            }
        }
        printf("%.3f\n", ans);
    }
    return 0;
}

void swap(_dev *a, _dev *b)
{
    int tmpbandwith=a->bandwith; 
    a->bandwith=b->bandwith;
    b->bandwith=tmpbandwith;
    int tmpprice=a->price;
    a->price=b->price;
    b->price=tmpprice;
}

void sort(_dev *head, _dev *tail)
{
    _dev *left=head, *right=tail;
    int midprice=(head+(tail-head)/2)->price;
    while(left<right){
        while(left->price<midprice) { ++left; }
        while(right->price>midprice) { --right; }
        if(left<=right){ swap(left++,right--); }
    }
    if(left<tail) { sort(left, tail); }
    if(right>head) { sort(head, right); }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值