用的暴搜,枚举每一个可能的带宽,维护一个最大的b/p,即答案;
google了下,还有其他思想,
对带宽排序:离散化思想,
枚举从最小带宽(每一行的最小值中的最小值)到最大带宽(每一行的最大值中的最小值)之间的值:贪心思想
b/p是一个关于b的单峰函数:3分思想。(用这个在加上二分查找和快排优化的话应该可以0msAC,以后回过头再重做吧,先留着,太菜了。)
我的AC代码:
# include <stdlib.h> # include <string.h> # include <string> # include <stdio.h> struct device { int b; int p; }; device d[110][110]; int sum; int cmp(const void *x, const void *y) { return ((device*)(x))->b - ((device*)(y))->b; } int go(int m) { for (int i = 0; i < m; ++ i) { qsort (d[i] + 1, d[i][0].b, sizeof(device), cmp); #ifdef DEBUG for (int j = 1; j <= d[i][0].b; ++ j) { printf ("%d-%d ", d[i][j].b, d[i][j].p); } printf ("\n"); #endif } double ans = 0; int up = 0; int down = 0; for (int i = 0; i < m; ++ i) { for (int j = 1; j <= d[i][0].b; ++ j) { up = d[i][j].b; down = d[i][j].p; for (int x = 0; x < m; ++ x) { if (x == i) continue; int min = 99999999; for (int y = 1; y <= d[x][0].b; ++ y) { if (d[x][y].b < up) continue; if (d[x][y].p < min) { min = d[x][y].p; } } down += min; } double tmp = (double)up / down; #ifdef DEBUG printf ("%.3lf\n", tmp); #endif ans = ans > tmp ? ans : tmp; } } printf ("%.3lf\n", ans); return 0; } int main () { int n,m; scanf ("%d", &n); while (n -- ) { scanf ("%d", &m); for (int i = 0; i < m; ++ i) { int t; scanf ("%d", &t); d[i][0].p = d[i][0].b = t; for (int j = 1; j <= t; ++ j) { scanf ("%d %d", &(d[i][j].b), &(d[i][j].p)); } } go(m); } return 0; }
大神的3分代码:
#include <iostream> #include <algorithm> #include <cmath> using namespace std; int n; int t; int len[111]; int b[111][111]; int p[111][111]; int a[222222]; int m; double calc(int x) { double sum(0); for (int i=1; i<=n; i++) { int xiao = 2147483647; for (int j=1; j<=len[i]; j++) if (b[i][j] >= x) xiao = min(xiao, p[i][j]); sum += xiao; } return x / sum; } int main(void) { int i,j,k,ci,cici,cicici; for (scanf("%d", &t); t; t--) { scanf("%d", &n); for (i=1; i<=n; i++) { scanf("%d", &len[i]); for (j=1; j<=len[i]; j++) { scanf("%d%d", &b[i][j], &p[i][j]); a[++m] = b[i][j]; } } sort(a+1, a+1+m); int left = 1, right = m, mid1, mid2; double f1, f2; while(left + 1 < right) { mid1 = (left + right) / 2; mid2 = (mid1 + right) / 2; f1 = calc(a[mid1]); f2 = calc(a[mid2]); if (f1 < f2) left = mid1; else right = mid2; } printf("%.3lf\n", max(calc(a[left]), calc(a[right]))); } return 0; }