【题意】:给出n个tests,每个test有a和b两个值,现要求你从这n个test中选出k个test使得这k个test中a的和除以b的和最大。
【题解】:好明显的01分数规划。
设集合x[],x[i]=0表示不选第i个test,x[i]=1表示选第i个test.
既我们要r = (∑a[i]*x[i]) / (∑b[i]*x[i]) 最大,且∑x[i] = k.
然后要构造子问题,详细的不想写了好麻烦。
最后上二分或者dinkelbach即可。
【代码】:
1 #include "iostream"
2 #include "cstdio"
3 #include "cstring"
4 #include "algorithm"
5 #include "vector"
6 #include "queue"
7 #include "cmath"
8 #include "string"
9 #include "cctype"
10 #include "map"
11 #include "iomanip"
12 using namespace std;
13 #define pb push_back
14 #define lc(x) (x << 1)
15 #define rc(x) (x << 1 | 1)
16 #define lowbit(x) (x & (-x))
17 #define ll long long
18 #define eps 1e-6
19 #define maxn 1050
20 int n, k;
21
22 struct Point {
23 int a, b;
24 double c;
25 bool operator <(const Point &x) const {
26 return c < x.c;
27 }
28 }p[maxn];
29
30 double work(double l) {
31 for(int i = 0; i < n; i++) p[i].c = 1.0 * p[i].a - l * p[i].b;
32 sort(p, p + n);
33 double sum = 0.0, suma = 0.0, sumb = 0.0;
34 for(int i = k; i < n; i++) sum += p[i].c, suma += p[i].a, sumb += p[i].b;
35 return suma / sumb;
36 }
37
38 void solve() {
39 double ans = 0.0, tmp = 0.0;
40 while(1) {
41 tmp = work(ans);
42 if(fabs(tmp - ans) < eps) break;
43 ans = tmp;
44 }
45 printf("%d\n", (int)(100.0 * (tmp + 0.005)));
46 }
47
48 int main() {
49 while(~scanf("%d%d", &n, &k)) {
50 if(!n && !k) break;
51 for(int i = 0; i < n; i++) scanf("%d", &p[i].a);
52 for(int i = 0; i < n; i++) scanf("%d", &p[i].b);
53 solve();
54 }
55 return 0;
56 }
57