poj 1018 Communication System(枚举)

本文介绍了一种用于选择通信系统中设备的算法,旨在通过最大化带宽与价格比(B/P),来挑选性价比最高的组合。文章详细解释了为何简单的设备级B/P最大化策略不可行,并提出了一种通过枚举最小带宽进行优化的方法。

大致题意:

某公司要建立一套通信系统,该通信系统需要n种设备,而每种设备分别可以有m1、m2、m3、...、mn个厂家提供生产,而每个厂家生产的同种设备都会存在两个方面的差别:带宽bandwidths 和 价格prices。

现在每种设备都各需要1个,考虑到性价比问题,要求所挑选出来的n件设备,要使得B/P最大。

其中B为这n件设备的带宽的最小值,P为这n件设备的总价。


错误思想:首先,以为只用算出每种设备的B/P ,挑选出每种中最大的计算B/P就可以得到结果,但是实际上,虽然每种的B/P可达到最大,但是不能保证在总体情况下B是每种设备中带宽最小。


思路: 首先固定一个B,假设该B是所选设备中最小的情况(枚举所有的设备的带宽B)。然后再将每种设备的带宽与之比较,若大于等于B且其单价最小,则说明当前B下,B/P是最小的,然后将所有B/P逐个比较,得到最大值,则为结果。


代码(参考别人所得):

#include<iostream>
using namespace std;
int main()
{
    int b[110][110],p[110][110],flag[32767],m[110];
    int t,n,min,max;
    double result; 
    int low=99999999,heigh = 0;
    scanf("%d",&t);
    while(t--)
    {
         scanf("%d",&n);
         low=min=99999999; heigh =max= 0;
         memset(flag,0,sizeof(flag));
         for(int i=0;i<n;i++)
         {
                 scanf("%d",&m[i]);
                 for(int j=0;j<m[i];j++)
                 {
                      scanf("%d%d",&b[i][j],&p[i][j]);
                      flag[b[i][j]] = 1; //用flag标记,该带宽存在 
                      if(min>b[i][j]) min=b[i][j];
                      if(max<b[i][j])  max=b[i][j]; 
                 }
         }
         if(low > min) low = min;
         if(heigh < max) heigh = max;
        // cout<<"low= "<<low<<" heigh="<<heigh<<endl;
         int sum;
         result = 0;
         for(int i=low ; i<= heigh;i++) //枚举每个可能的最小带宽B 
         {
                 if(flag[i])  //只有该带宽值存在时,枚举其他设备才有意义 
                 {//cout<<"************i= "<<i<<endl;
                       sum = 0;
                       for(int j=0;j<n;j++)
                       {int pow=999999999;
                               for(int k=0;k<m[j];k++)
                               {
                                       if(b[j][k]>=i && p[j][k] < pow)//保证带宽B固定i时,sum最小(即每种设备的价格最小),才能使B/P最大 
                                       {pow = p[j][k]; }
                               }
                               sum+=pow;
                       }
                       double temp = (double) i*1.0/sum;
                       if(result < temp) result=temp;
                 }
         }
         printf("%.3lf\n",result);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值