首页 > 代码库 > NYOJ-914 Youth的最大化(贪心)

NYOJ-914 Youth的最大化(贪心)

Youth的最大化

时间限制:1000 ms | 内存限制:65535 KB 
难度:4 
描述 
Yougth现在有n个物品的重量和价值分别是Wi和Vi,你能帮他从中选出k个物品使得单位重量的价值最大吗?

输入

有多组测试数据 
每组测试数据第一行有两个数n和k,接下来一行有n个数Wi和Vi。 
(1<=k=n<=10000) (1<=Wi,Vi<=1000000)

输出

输出使得单位价值的最大值。(保留两位小数)

样例输入

3 2 
2 2 
5 3 
2 1

样例输出

0.75

 

贪心策略:

贪心+二分: 
k个物品的最大单位价值 一定大于0且小于单个物品的最大单位价值。求出单个物品的最大单位价值,然后二分查找即可。

 

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <stdbool.h>
 4 #define imax(x,y) (x>y?x:y)
 5 #define MAXN 10005
 6 int n, k;
 7 double w[MAXN], v[MAXN];
 8 int i;
 9 double need[MAXN];
10 int compare(const void * p1, const void * p2) {
11     return *(double *)p1 < *(double *)p2 ? 1 : -1;
12 }
13 bool judge(double x) {
14     // 算出当前物品达到均值x的代价,
15     //负数表示比均值小,正数反之
16     for (i = 0; i < n; i++) {
17         need[i] = v[i] - x*w[i];
18     }
19 
20     //将need数组从大到小排序
21     qsort(need, n, sizeof(need[0]), compare);
22 
23     // 取前k个,算出它们所需代价之和
24     // 若为正,则代表超过均值,代表均值不够大,向右区间查找;为负反之
25     double all_need = 0;
26     for (i = 0; i < k; i++) {
27         all_need += need[i];
28     }
29     return all_need >= 0 ? true : false;
30 }
31 double binary_search(double right) {
32     double left = 0;
33     while (right - left > 0.00001) {
34         double mid = (left + right) / 2;
35         if (judge(mid))
36             left = mid;
37         else
38             right = mid;
39     }
40     return left;
41 }
42 int main(void)
43 {
44     while (scanf("%d %d", &n, &k)!=EOF) {
45         double max_ratio = 0;
46         for (i = 0; i < n; i++) {
47             scanf("%lf %lf", &w[i], &v[i]);
48             max_ratio = imax(max_ratio,(v[i]/w[i]));
49         }
50         //printf("%lf\n", max_ratio);
51         double res = binary_search(max_ratio);
52         printf("%.2lf\n", res);
53     }
54     return 0;
55 }

 

NYOJ-914 Youth的最大化(贪心)