POJ1018贪心(多路归并的想法)

该博客介绍了如何使用贪心算法解决POJ1018问题,通过多路归并的思想,对每个服务器的网线选择进行排序和预处理,以找到最大比值的最小带宽和总花费。博主详细阐述了算法实现过程,并提供了AC的C++代码实现。
摘要由CSDN通过智能技术生成
题意:
     有n个服务器,每个服务器都要安装网线(必须也只能安装一个),然后每个服务器都有mi种选择网线的方式,每种方式两个参数,一个是速度b,另一个是价钱p,然后让你找到一个最大的比值 minb/sump,就是所有的选择中最小的那个速度,必上话的钱的总和。


思路: 
      这个题目按照讨论组里面的说法估计做法很多,不管了,说下我自己的做法吧,我的做法有点像操作系统里面那个多路归并(如果没记错是叫这个,做题的时候突然想到这个方式,试了下,还真行),具体是这样,枚举最小的b,也就是最小的那个带宽,对于每个服务器,我们可以先把他所有的可选择项都按照带宽从小到大排序,排序后再倒着预处理得到每个选项后面中最小的那个花费,全部这样处理完之后就得到了一个二维的表,然后我们开始枚举,每个表都是根据带宽从小到大排序的,这样所有中最小的那个肯定就是某一个的第一项,我们O(n)的时间找到第一项,以这一项的带宽为最小带宽,花费是当前这个选项的花费,其他的就选最小的花费,然后删除找到的这一项,就这样一直找到头一个服务器的选项全都用完了位置,还有就是删除项的时候可以开一个一维数组,记录当前这个服务器已经用到第几项了,删除第i个服务器的当前项,直接mk[i]++就行了,16msAC,总的时间复杂度最坏应该是 O(n*n*n) 1000000吧。感觉思路有点瞎扯了,呵呵,题目不难,瞎扯就瞎扯吧,好就说这些。


#include<stdio.h>
#include<string.h>
#include<algorithm>


#define N 100 + 10
#define INF 1000000000


using namespace std;


typedef struct
{
    int b ,p ,minp;
}NODE;


NODE node[N][N];
int now[N] ,num[N];


bool camp(NODE a ,NODE b)
{
    return a.b < b.b;
}


int main ()
{
    int t ,i ,j ,n ,tmp ,sn;
    scanf("%d" ,&t);
    while(t--)
    {
        scanf("%d" ,&n);
        for(i = 1 ,sn = 0 ;i <= n ;i ++)
        {
            scanf("%d" ,&num[i]);
            sn += num[i];
            for(j = 1 ;j <= num[i] ;j ++)
            scanf("%d %d" ,&node[i][j].b ,&node[i][j].p);
            sort(node[i] + 1 ,node[i] + num[i] + 1 ,camp);
            for(j = num[i] ;j >= 1 ;j --)
            {
                if(j == num[i] || tmp > node[i][j].p)
                tmp = node[i][j].p;
                node[i][j].minp = tmp;
            }
            now[i] = 1;
        }
        double Ans = 0;
        int nowb ,nowp;
        while(sn--)
        {
            nowb = INF;
            nowp = 0;
            int mkbreak = 0;
            for(i = 1 ;i <= n ;i ++)
            {
                if(now[i] > num[i]) mkbreak = 1;
                if(nowb > node[i][now[i]].b)
                nowb = node[i][now[i]].b;
            }
            if(mkbreak) break;
            int mk = 0;
            for(i = 1 ;i <= n ;i ++)
            {
                //if(now[i] > num[i]) continue;
                if(!mk && nowb == node[i][now[i]].b)
                {
                    mk = 1;
                    nowp += node[i][now[i]].p;
                    now[i] ++;
                }
                else nowp += node[i][now[i]].minp;
            }
            if(Ans < nowb * 1.0 / nowp)
            Ans = nowb * 1.0 / nowp;
        }
        printf("%.3lf\n" ,Ans);
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值