ZOJ 1409 Communication System

这题用的是贪心算法,不过在贪心之前还是要进行部分处理的。

首先就是题目要求B/P尽可能的大,所以P应该尽可能的小,B应该尽可能的大。但是B和P的处理方式是不一样的,B是所有带宽中最小的那一个,P是所有设备的总价钱,所以我能想到一个方法就是一个一个的枚举B,本来我是不敢这样想的,可是题目给的时间比较长,我觉得应该问题不大,当我运行之后,竟然只是0ms,让我吃了一惊。然后再选择设备,这时候就要用到贪心:

给定一个band,对于一个设备,在各个生产厂家之间的选择,显然带宽要比band大,在这个中选择价钱最便宜的。

我的具体处理细节如下:

1、对所有的band进行升序排序,枚举的时候从最小的开始,当枚举到一个band,某一个设备无法选出,也就是说该设备的各个生产厂家的带宽都没有band大,那么就结束了。

2、对每个设备的band进行降序排序,这样在查找最小的price的时候比较方便。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<stack>
#include<queue>
using namespace std;
const int inf=1<<28;
int band[10002],num[102];
struct Device
{
    int band;
    int price;
}device[102][102];
int n,m;
int solve(int t)
{
    int t1=0,t2;
    for(int i=1;i<=n;i++)
    {
        t2=inf;
        for(int j=1;j<=num[i];j++)
        {
            if(device[i][j].band<t)
                break;
            if(t2>device[i][j].price)
                t2=device[i][j].price;
        }
        if(t2==inf)
            return -1;
        t1+=t2;
    }
    return t1;
}
bool cmp(Device a,Device b)
{
    return a.band>b.band;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        int top=1;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&m);
            num[i]=m;
            for(int j=1;j<=m;j++)
            {
                scanf("%d%d",&device[i][j].band,&device[i][j].price);
                band[top++]=device[i][j].band;
            }
        }
        sort(band+1,band+top);
        for(int i=1;i<=n;i++)
            sort(device[i]+1,device[i]+num[i]+1,cmp);
        int t_band=0,sum;
        double ans=0.0;
        for(int i=1;i<top;i++)
        {
            if(band[i]==t_band)//如果相同的带宽已经处理过,那么就不用处理了
                continue;
            t_band=band[i];
            sum=solve(band[i]);
            if(sum==-1)
                break;
            double b_p=band[i]*1.0/sum;
            if(ans<b_p)
                ans=b_p;
        }
        printf("%.3lf\n",ans);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值