题意:有n种设备,每种设备都有若干制造商,不同制造商提供设备的带宽和价格不同,现需要每种设备各一个,总带宽为这n个设备的最小带宽,总价格为这n个设备的价格之和,求最大的总带宽/总价格。
解法:枚举+剪枝。枚举最小带宽,将所有设备进行排序,排序的优先级为b->p->id,两个剪枝:1.重复的b不需要枚举。2.当前的b无法满足让所有种类的设备都有设备的带宽大于等于b的时候不需要继续枚举。
剪枝效果拔群……觉得是因为数据有点弱?总之32ms就过了……看到网上题解有说dp的……想了一下……没说b的范围……不知道怎么dp……orz
代码:
#include<stdio.h> #include<iostream> #include<algorithm> #include<string> #include<string.h> #include<math.h> #include<limits.h> #include<time.h> #include<stdlib.h> #include<map> #include<queue> #include<set> #include<stack> #include<vector> #define LL long long using namespace std; struct node { int b, p, id; bool operator < (const node &tmp) const { if(b == tmp.b) { if(p == tmp.p) return id < tmp.id; return p < tmp.p; } return b < tmp.b; } }dev[10005]; int main() { int T; scanf("%d", &T); while(T--) { int n; scanf("%d", &n); int cnt = 0; for(int i = 0; i < n; i++) { int m; scanf("%d", &m); while(m--) { int b, p; scanf("%d%d", &b, &p); dev[cnt].b = b; dev[cnt].p = p; dev[cnt++].id = i; } } sort(dev, dev + cnt); double ans = 0.0; for(int i = 0; i < cnt; i++) { if(!i || dev[i].b != dev[i - 1].b)//第一个剪枝 { int now = dev[i].b;//当前枚举的b int sumnum = 0, sum = 0;//已选设备种数,总价格 bool vis[105] = {0};//是否选过这种设备 int price[105];//这种设备中满足条件的最低价格 memset(price, 0x3f3f3f3f, sizeof price); for(int j = 0; j < cnt; j++) { if(dev[j].b >= now) { if(!vis[dev[j].id]) { vis[dev[j].id] = 1; sumnum++; sum += dev[j].p; price[dev[j].id] = dev[j].p; } else { if(dev[j].p < price[dev[j].id]) { sum -= price[dev[j].id]; sum += dev[j].p; price[dev[j].id] = dev[j].p; } } } } if(sumnum == n) ans = max(ans, (double)now / sum); else break; } } printf("%.3lf ", ans); } return 0; }