贪心算法:先排序,再枚举最小带宽(B),每次更新当前最小花费(P)和以及答案(ans)
#include <cstdio> #include <algorithm> using namespace std; struct data {int b,p;} a[101][101]; int m[101],B[100001]; bool cmp(const data &A,const data &B) { if(A.b==B.b)return A.p > B.p; return A.b < B.b; } int main() { int t,n; for(scanf("%d",&t);t--;) { scanf("%d",&n); int i_B=0; for(int i=1; i<=n; i++) { scanf("%d",&m[i]); for(int j=1; j<=m[i]; j++) { scanf("%d%d",&a[i][j].b,&a[i][j].p); B[++i_B]=a[i][j].b; } sort(a[i]+1,a[i]+m[i]+1,cmp); } sort(B+1,B+i_B+1); double ans=0;bool flag; for(int i=1; i<=i_B; i++) { //枚举B的值 if(B[i]==B[i+1] && i<i_B) continue;//剪枝 int sum_p=0,min_p; for(int j=1; j<=n; j++) { flag=true,min_p=2147483647; for(int k=1; k<=m[j]; k++) if(a[j][k].b>=B[i] && a[j][k].p<min_p) min_p=a[j][k].p,flag=false; if(flag) break; sum_p+=min_p; } if(flag) break; ans=max(ans,(double)B[i]/sum_p); } printf("%.3f\n",ans); } return 0; }