题目大意
需要n个设备,第i个设备有mi个厂商,每个厂商做该设备有两个参数,带宽和价格,每个设备从其中一个厂商处购得,现在定义B为n个设备中带宽的最小值,P为n个设备的总价值,求B/P的最大值
思路分析
rank终于到破5000了,感动。不过这道题也是蛮波折的还是自己太菜了 。没想到可以这样贪心,再知道了题解之后仍然思考了挺久的关于该算法的正确性。也给自己提个醒,忽视了枚举的作用。
思路:从小到大枚举带宽,对于第i个设备,在mi个厂商中选择带宽不小于当前枚举值且价格最小的那个,正确性在于求B/P的最大值,我们就要让B尽量大,让P尽量小,因为我们在枚举B的时候取的是大于等于B的带宽,所以当前的分子B就是枚举值,然后再找满足带宽大小约束的价格尽量小的加起来就是分母P,因此对于每一个带宽我们都有一个最优解,最后取全局最优即可。
唯一令人欣慰的是知道题解一遍过了/(ㄒoㄒ)/~~
//memory:364K time:32ms
#include<iostream>
#include<string>
#include<string.h>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#include<set>
using namespace std;
#define MAX 105
#define ll int
#define inf 0x3ffffff
struct E {
ll b, p;
E(ll x = 0, ll y = 0) { b = x, p = y; }
};
bool cmp(E e1, E e2) {
return e1.b > e2.b;//按照带宽排序
}
vector< E > a[MAX];
int main() {
ll t, n, m, x, y; scanf("%d", &t);
vector<ll> v;
for (int b = 0; b < t; b++) {
scanf("%d", &n);
for (int i = 0; i < n; i++)a[i].clear();
for (int i = 0; i < n; i++) {
scanf("%d", &m);
for (int j = 0; j < m; j++) {
scanf("%d%d", &x, &y);
a[i].push_back(E(x, y));
v.push_back(x);//把所有的价格集中起来
}
sort(a[i].begin(), a[i].end(), cmp);//根据带宽从大到小排序
}
sort(v.begin(), v.end());
ll sign = 1;//如果有一个设备没有任何带宽大于v[i]的选择 那么就退出循环
double res = 0;
for (int i = 0; i < v.size() && sign; i++) {
if (i == 0 || v[i] != v[i - 1]) {//去重,找到不重复的带宽
ll B = inf, P = 0, tb, tp;
for (int j = 0; j < n&&sign; j++) {//遍历所有的element
if (a[j][0].b < v[i]) { sign = 0; break; }//最大的B都小于v[i],退出
tb = 0, tp = inf;
for (int k = 0; k < a[j].size() && sign; k++) {
if (a[j][k].b < v[i])break; //之后的带宽都没有v[i]大
if (a[j][k].p < tp) {
tp = a[j][k].p, tb = a[j][k].b;//选b大于v[i]的最小price
}
}
B = min(B, tb), P += tp;
}
if (sign)res = max(res, 1.0*B / P);
}
}
printf("%.3f\n", res);
}
}