Dropping tests(poj 2976)
原题链接
题目类型:0/1分划
思路一:枚举
已知n的最大值为1000,如果进行枚举的话,在1000个中选择500个对应的组合数如下所示,因此枚举是不可能的。
思路二:0/1分数规划
参考思路
当最大的一组解>0的时候,代表存在一组解,能够获得更大的值,因此移动上界,那为什么其余情况下为什么要移动下界呢?(照理来说应该为取最大的都<0),那么应该移动下界,那么中间的情况呢?
初始的l和r应该如何确定?->由于 ai 一定是会小于 bi 的,因此可以设置初始的区间为[0,1]
#include<iostream>
#include<algorithm>
using namespace std;
#define NMAX 1003
int a[NMAX];
int b[NMAX];
double c[NMAX];
int n, k;
int check(double ans) {
double res = 0;
for (int i = 0; i < n; i++) c[i] = a[i] - ans * b[i];
sort(c, c + n);
for (int i = n - 1; i >= k; i--) res += c[i];
if (res > 0) return 1;
else return 0;
}
int main() {
while (1) {
cin >> n >> k;
if (!n && !k) break;
for (int i = 0; i < n; i++) cin >> a[i];
for (int i = 0; i < n; i++) cin >> b[i];
double left = 0, right = 1, mid ;
while (right - left > 1e-4) {
//printf("%g %g\n", left, right);
mid = (left + right) / 2; //注意需要改变mid的具体值
if (check(mid)) left = mid;
else right = mid;
}
//输出的方法一:存在的问题是没有四舍五入
//int cur = max((int)100 * left, (int)100 * right ); //取较大的那个
//printf("%d\n",cur);
// 输出的方式二:存在的问题是格式化字符串会转变错误
//printf("%d\n", (int)100 * left); 注意这样输出是不正确的!!!
printf("%.0f\n", left * 100);
}
}
tip:
1.对于%m.n 其中m代表的是域宽,而n则代表的是小数的位数。