POJ 1018 Communication System

题意:有n种设备,每种设备都有若干制造商,不同制造商提供设备的带宽和价格不同,现需要每种设备各一个,总带宽为这n个设备的最小带宽,总价格为这n个设备的价格之和,求最大的总带宽/总价格。

解法:枚举+剪枝。枚举最小带宽,将所有设备进行排序,排序的优先级为b->p->id,两个剪枝:1.重复的b不需要枚举。2.当前的b无法满足让所有种类的设备都有设备的带宽大于等于b的时候不需要继续枚举。

剪枝效果拔群……觉得是因为数据有点弱?总之32ms就过了……看到网上题解有说dp的……想了一下……没说b的范围……不知道怎么dp……orz

代码:

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string>
#include<string.h>
#include<math.h>
#include<limits.h>
#include<time.h>
#include<stdlib.h>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<vector>
#define LL long long
using namespace std;
struct node
{
    int b, p, id;
    bool operator < (const node &tmp) const
    {
        if(b == tmp.b)
        {
            if(p == tmp.p)
                return id < tmp.id;
            return p < tmp.p;
        }
        return b < tmp.b;
    }
}dev[10005];

int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        int n;
        scanf("%d", &n);
        int cnt = 0;
        for(int i = 0; i < n; i++)
        {
            int m;
            scanf("%d", &m);
            while(m--)
            {
                int b, p;
                scanf("%d%d", &b, &p);
                dev[cnt].b = b;
                dev[cnt].p = p;
                dev[cnt++].id = i;
            }
        }
        sort(dev, dev + cnt);
        double ans = 0.0;
        for(int i = 0; i < cnt; i++)
        {
            if(!i || dev[i].b != dev[i - 1].b)//第一个剪枝
            {
                int now = dev[i].b;//当前枚举的b
                int sumnum = 0, sum = 0;//已选设备种数,总价格
                bool vis[105] = {0};//是否选过这种设备
                int price[105];//这种设备中满足条件的最低价格
                memset(price, 0x3f3f3f3f, sizeof price);
                for(int j = 0; j < cnt; j++)
                {
                    if(dev[j].b >= now)
                    {
                        if(!vis[dev[j].id])
                        {
                            vis[dev[j].id] = 1;
                            sumnum++;
                            sum += dev[j].p; 
                            price[dev[j].id] = dev[j].p;
                        }
                        else
                        {
                            if(dev[j].p < price[dev[j].id])
                            {
                                sum -= price[dev[j].id];
                                sum += dev[j].p;
                                price[dev[j].id] = dev[j].p;
                            }
                        }
                    }
                }
                if(sumnum == n)
                    ans = max(ans, (double)now / sum);
                else
                    break;
            }
        }
        printf("%.3lf
", ans);
    }
    return 0;
}

  

原文地址:https://www.cnblogs.com/Apro/p/4857630.html