POJ 3111 K Best ( 二分 )
2024-10-07 08:33:58
题意 : 给出 N 个物品的价值和重量,然后要求选出 K 个物品使得选出来物品的单位重量价值最大,最后输出被选物品的编号。
分析 :
很容易去想先算出每个物品的单位价值然后升序排序取前 K 个,但是很可惜这样的做法是错误的。
例如 : N = 3、K = 2、{ w、v } = { {2,2}、{5,4}、{2,1} },贪心的方法是选出 1、2,但是正确答案是选出1、3
这题的正确做法是利用二分,难点就在如何判定二分出来的每一个单位重量价值是否是一个可行答案
假设当前二分出来的答案是 x
那么就要求选出来的某 K 个物品的组合使得 ∑ vi / ∑ wi ≥ x 成立
变形得到 ∑ ( vi - wi * x ) ≥ 0
那么最后就变成了对于当前的 x 对所有物品的 vi - wi * x 进行排序
并判断前 K 大的是否大于等于 0 ,如果是则说明可行!
#include<algorithm> #include<stdio.h> #include<math.h> using namespace std; ; ; ; struct Jewel{ int id, v, w; }arr[maxn]; struct st{ double val; int id; bool operator < (const st & rhs) const{ return this->val > rhs.val; }; }c[maxn]; int N, K, ans[maxn]; bool OK(double key) { ; i<=N; i++){ c[i].val = arr[i].v - arr[i].w * key; c[i].id = arr[i].id; } sort(c+, c++N); ; ; i<=K; i++) sum += c[i].val; if(sum >= 0.0){ ; i<=K; i++) ans[i] = c[i].id; return true; }else return false; } int main(void) { while(~scanf("%d %d", &N, &K)){ ; i<=N; i++){ if(i <= K) ans[i] = i;///注意要提前给 ans 赋上初值,因为 OK 函数可能永远不为真,例如所有物品的 v = 0 arr[i].id = i; scanf("%d %d", &arr[i].v, &arr[i].w); } double L = 0.0; double R = INF; while(R - L > EPS){ double mid = ( R + L ) / 2.0; if(OK(mid)) L = mid; else R = mid; } ; i<=K; i++){ printf("%d", ans[i]); if(i < K) putchar(' '); else putchar('\n'); } } ; }
最新文章
- 开博了,hello world
- RestSharp简单扩展
- 161214、oracle查询表信息
- c# 调用MD5CryptoServiceProvider出现 System.InvalidOperationException: This implementation is not part of the Windows Platform FIPS validated cryptographic algorithms.
- Android线程和线程池
- java jvm学习笔记一
- JavaScript进阶(三) 值传递和引用传递
- jQuery第一章
- LeetCode 111. Minimum Depth of Binary Tree (二叉树最小的深度)
- 关于GCJ02和WGS84坐标系的一点实验
- 【题解】UVA11362 Phone List
- WPF 10天修炼 第六天- 系统属性和常用控件
- iphone html5页面禁止点击数字就打电话
- Linux3.10.0块IO子系统流程(5)-- 为SCSI命令准备聚散列表
- 【linux】tar压缩不包含路径
- 字符集和编码——Unicode(UTF&;UCS)深度历险
- Mysql Innodb 表碎片整理
- 2016.5.15——leetcode:Number of 1 Bits ,
- django的单元测试框架unittest、覆盖率
- 【BZOJ】3329: Xorequ