题目大意:有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); } }