poj1018

题目大意:有n条生产线,每条线需要一台机器,每台机器有相应的带宽B和价格P,现在给出n条线的可选机器,要你每条线选一台,使得min{Bi}/sum{Pi}最大。

思路:把每台机器的带宽、价格、线号捆绑在一起,在一维数组上按带宽从小到大排序。枚举排序后的数组。

剪枝,记录每条线上带宽最大值,当枚举到的带宽比任何一条线的最大带宽都要大就可以停止枚举了,因为枚举到的机器代表所选的机器中带宽最小的一个。

#include <iostream>
#include <cmath>
#include <stdio.h>
#include <algorithm>
#include <ctime>
#include <vector>
#include <cstring>
#include <map>
using namespace std;
#define LL long long
#define ULL unsigned long long
//#define REP(i,n) for(int i=0;i<n;++i)
#define REP(i,a,b) for(int i=a;i<=b;++i)
#define INFLL (1LL)<<62
#define mset(a) memset(a,0,sizeof a)
#define FR(a) freopen(a,"r",stdin)
#define FW(a) freopen(a,"w",stdout)
#define PI 3.141592654
const LL MOD = 1000000007;
const int maxn = (int)5e4+10;
int t,n;
struct M{
	int B,P,id;
}machine[10011];
int price[111];
bool cmp(M a,M b)
{
	if(a.B==b.B){
		return (a.P==b.P)?a.id<b.id:a.P<b.P;
	}
	return a.B<b.B;
}
int main()
{
	cin>>t;
	while (t--)
	{
		int m[111];
		scanf("%d",&n);
		int k=0;
		int minb=10000000;
		REP(i,0,n-1){
			int maxb=0;
			scanf("%d",m+i);
			REP(j,0,m[i]-1){
				scanf("%d%d",&machine[k].B,&machine[k].P);
				machine[k].id=i;
				maxb=max(maxb,machine[k].B);
				k++;
			}
			minb=min(maxb,minb);
		}
		double maxbp=0;
		sort(machine,machine+k,cmp);
		REP(i,0,k-1){
			REP(j,0,n-1) price[j]=1000000000;
			if(machine[i].B>minb) break;
			int d=machine[i].id;
			price[d]=machine[i].P;
			REP(j,i+1,k-1){
				if(machine[j].id==d) continue;
				price[machine[j].id]=min(price[machine[j].id],machine[j].P);
			}
			double sum=0;
			REP(j,0,n-1) sum+=price[j];
			maxbp=max(maxbp,machine[i].B/sum);
		}


		printf("%.3lf\n",maxbp);
	}
}


你可能感兴趣的:(poj1018)