题目是说,要采购n个设备,每个设备i有m[i]个生产商,第j个生产商的带宽是b[i][j],价格是p[i][j],求一种采购方案,使得B/P最大。这里B是指所有设备中带宽b的最小值,P是指总价格。只需要输出B/P。
很容易想到枚举,将每个设备的每个生产商作为B,再依次用贪心选择满足b>=B且p最小的其他设备。不断更新这个B/P值,最后可得到最优值。
不过这样子算下来时间复杂度偏大,所以还得优化。
注意到某些生产商的b值不可能作为B,这个条件可以作为剪枝。事先计算好maxB,表示B值上限。
对于每个设备i,求出b[i][j]的最大值,最后取这些最大值中的最小值,即是maxB。如果B>maxB,那么就会有设备所有生产商都不满足条件b>=B,矛盾。
网上看到的解法还有很多优化处理,比如排序等等,但我只用这一个剪枝已经可以AC。
还有一点,题目最后要求Round 3位小数,我直接截断(没有四舍五入)居然也过了。
附上代码:
#include <iostream>
#include <iomanip>
#define INF 0x7fffffff
using namespace std;
int main()
{
int T;
cin >> T;
while (T--)
{
int n, m[101], b[101][101], p[101][101], maxB = INF;
cin >> n;
for (int i = 1; i <= n; i++)
{
int max = 0;
cin >> m[i];
for (int j = 1; j <= m[i]; j++)
{
cin >> b[i][j] >> p[i][j];
if (b[i][j] > max)
max = b[i][j];
}
if (max < maxB)
maxB = max;
}
/* enumerate each manufacturer, assuming it has the minimal bandwidth of all,
then find the minimal sum of prices. */
double ans = 0;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m[i]; j++)
{
int B = b[i][j], P = p[i][j];
bool ok = true;
if (B > maxB) continue;
/* start searching */
for (int ii = 1; ii <= n; ii++)
{
if (ii != i)
{
int min_p = INF;
for (int jj = 1; jj <= m[ii]; jj++)
{
if (b[ii][jj] >= B && p[ii][jj] < min_p)
min_p = p[ii][jj];
}
P += min_p;
}
}
if ((double)B / P > ans)
ans = (double)B / P;
}
}
cout << setiosflags(ios::fixed) << setprecision(3) << ans << endl;
}
return 0;
}