题意简述:
有n种设备,每种设备有m种生产商可以选择,每个生产商制造的设备带宽和价格不同
令B为所有选择的设备的最小带宽,P为所有选择的设备的价格之和
为每个设备选择生产商使得B/P最大
实现:
#include <iostream>
#include <vector>
#include <iomanip>
using namespace std;
#define inf 1000000
int min(int a, int b) {
return a < b ? a : b;
}
int main(void) {
int cases_num;
cin >> cases_num;
while (cases_num--) {
int devices_num, max_bandwidth = 0;
cin >> devices_num;
vector<vector<int> > b(devices_num), p(devices_num);
vector<int> devices_choices; //保存每个设备有多少种不同类型
for (int i = 0; i < devices_num; i++) {
int choices_num;
cin >> choices_num;
devices_choices.push_back(choices_num);
int bandwidth, price;
for (int j = 0; j < choices_num; j++) {
cin >> bandwidth >> price;
if (bandwidth > max_bandwidth) max_bandwidth = bandwidth;
b[i].push_back(bandwidth);
p[i].push_back(price);
}
}
//dp[i][j]: 前i个(从0开始)设备的最大带宽为j时的最小价格
vector<vector<int> > dp(devices_num, vector<int>(max_bandwidth + 1, inf));
for (int i = 0; i < devices_num; i++) {
for (int j = 0; j <= max_bandwidth; j++) {
for (int m = 0; m < devices_choices[i]; m++) {
if (j <= b[i][m]) {
if (i == 0)
dp[i][j] = min(p[0][m], dp[0][j]);
else
dp[i][j] = min(dp[i - 1][j] + p[i][m], dp[i][j]);
}
}
}
}
double maxValue = 0;
for (int j = 0; j <= max_bandwidth; j++) {
if ((double)j / (double)dp[devices_num - 1][j] > maxValue)
maxValue = (double)j / (double)dp[devices_num - 1][j];
}
cout << fixed << setprecision(3) << maxValue << endl;
}
}
简单测试样例:
3
3
3 100 25 150 35 80 25
2 120 80 155 40
2 100 100 120 110
3
3 130 35 140 33 90 25
2 300 80 195 45
2 100 50 120 110
4
5 130 35 140 33 90 25 300 80 195 45
5 1300 135 1400 383 980 205 3080 890 1095 445
4 1200 135 400 383 980 205 308 890
2 1400 900 2400 1000
输出结果:
0.649
0.781
0.240