标签:
这题用的是贪心算法,不过在贪心之前还是要进行部分处理的。
首先就是题目要求B/P尽可能的大,所以P应该尽可能的小,B应该尽可能的大。但是B和P的处理方式是不一样的,B是所有带宽中最小的那一个,P是所有设备的总价钱,所以我能想到一个方法就是一个一个的枚举B,本来我是不敢这样想的,可是题目给的时间比较长,我觉得应该问题不大,当我运行之后,竟然只是0ms,让我吃了一惊。然后再选择设备,这时候就要用到贪心:
给定一个band,对于一个设备,在各个生产厂家之间的选择,显然带宽要比band大,在这个中选择价钱最便宜的。
我的具体处理细节如下:
1、对所有的band进行升序排序,枚举的时候从最小的开始,当枚举到一个band,某一个设备无法选出,也就是说该设备的各个生产厂家的带宽都没有band大,那么就结束了。
2、对每个设备的band进行降序排序,这样在查找最小的price的时候比较方便。
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #include<stack> #include<queue> using namespace std; const int inf=1<<28; int band[10002],num[102]; struct Device { int band; int price; }device[102][102]; int n,m; int solve(int t) { int t1=0,t2; for(int i=1;i<=n;i++) { t2=inf; for(int j=1;j<=num[i];j++) { if(device[i][j].band<t) break; if(t2>device[i][j].price) t2=device[i][j].price; } if(t2==inf) return -1; t1+=t2; } return t1; } bool cmp(Device a,Device b) { return a.band>b.band; } int main() { int t; scanf("%d",&t); while(t--) { scanf("%d",&n); int top=1; for(int i=1;i<=n;i++) { scanf("%d",&m); num[i]=m; for(int j=1;j<=m;j++) { scanf("%d%d",&device[i][j].band,&device[i][j].price); band[top++]=device[i][j].band; } } sort(band+1,band+top); for(int i=1;i<=n;i++) sort(device[i]+1,device[i]+num[i]+1,cmp); int t_band=0,sum; double ans=0.0; for(int i=1;i<top;i++) { if(band[i]==t_band)//如果相同的带宽已经处理过,那么就不用处理了 continue; t_band=band[i]; sum=solve(band[i]); if(sum==-1) break; double b_p=band[i]*1.0/sum; if(ans<b_p) ans=b_p; } printf("%.3lf\n",ans); } return 0; }
标签:
原文地址:http://blog.csdn.net/u013621213/article/details/43459877