标签:
题意:有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\n", ans);
}
return 0;
}
标签:
原文地址:http://www.cnblogs.com/Apro/p/4857630.html