二分查找,背包问题v3
来源:互联网 发布:unity3d摇杆八方向 编辑:程序博客网 时间:2024/06/05 00:10
https://vjudge.net/problem/51Nod-1257
二分方法, 我竟然傻傻的想动态规划, 而且竟然想不出来, 哪位仁兄过来指点指点
下面是二分
1257 背包问题 V3
基准时间限制:3 秒 空间限制:131072 KB 分值: 80 难度:5级算法题
收藏
关注
N个物品的体积为W1,W2……Wn(Wi为整数),与之相对应的价值为P1,P2……Pn(Pi为整数),从中选出K件物品(K <= N),使得单位体积的价值最大。
Input
第1行:包括2个数N, K(1 <= K <= N <= 50000)
第2 - N + 1行:每行2个数Wi, Pi(1 <= Wi, Pi <= 50000)
Output
输出单位体积的价值(用约分后的分数表示)。
Input示例
3 2
2 2
5 3
2 1
Output示例
3/4
原理就是利用二分求出来前最优解的前k项的单位体积最大值, 并筛选出来最优解的前k项
#include<iostream>#include<cstdio>#include<algorithm>using namespace std;const int LEN = 50000+50;int w[LEN];int p[LEN];struct T{ int ID; double v;}d[LEN];int gcd(int a,int b){ return b == 0?a:gcd(b,a%b);}bool cmp(const T &a,const T &b){ return a.v>b.v;}int main(void){ int N,K; cin>>N>>K; for(int i = 1; i <= N;++i) scanf("%d %d",&w[i],&p[i]); double l = 0,r = 50000.0*50000; while(r-l>1e-6) { double mid = l + (r-l)/2; for(int i = 1; i <= N; ++i) { d[i].v = p[i] - mid * w[i];//这是本题的关键 d[i].ID = i; } sort(d+1,d+N+1,cmp); double sum = 0; for(int i = 1; i <= K; ++i) sum += d[i].v; if(sum>0) l = mid;//sum大于零, 说明mid的值取得过小 else r = mid; } long long V = 0,H = 0; for(int i = 1; i <= K; ++i) { V += w[d[i].ID]; H += p[d[i].ID]; } int tmp = gcd(V,H); cout<<H/tmp<<"/"<<V/tmp<<endl; return 0;}
- 上面是 最初的代码, 我进行了一步步的优化
首先发现sort调用<运算符的方法比 采用函数的方法要快
struct T { int ID; double v; bool operator<(const T &a) { return v > a.v; }}d[LEN];
优化了大概一百毫秒的样子
下面优化了一下二分
#include<iostream>#include<cstdio>#include<algorithm>#include<cmath>using namespace std;const int LEN = 50000 + 50;int w[LEN];int p[LEN];struct T { int ID; double v; bool operator<(const T &a) { return v > a.v; }}d[LEN];int gcd(int a, int b){ return b == 0 ? a : gcd(b, a%b);}int main(void){ int N, K; cin >> N >> K; for (int i = 1; i <= N; ++i) scanf("%d %d", &w[i], &p[i]); double l = 1, r = 0; while (fabs(r - l)>1e-6) { r = l; for (int i = 1; i <= N; ++i) { d[i].v = p[i] - r * w[i]; d[i].ID = i; } sort(d + 1, d + N + 1); int V = 0, P = 0;; for (int i = 1; i <= K; ++i) { V += w[d[i].ID]; P += p[d[i].ID]; } l = P*1.0 / V; } long long V = 0, H = 0; for (int i = 1; i <= K; ++i) { V += w[d[i].ID]; H += p[d[i].ID]; } int tmp = gcd(V, H); cout << H / tmp << "/" << V / tmp << endl; return 0;}
阅读全文
0 0
- 二分查找,背包问题v3
- 51nod 1257 背包问题 V3(二分)
- 背包问题 V3
- 【51Nod1257】背包问题 V3
- 51nod 1257 背包问题 V3
- 51nod 1257 背包问题V3
- 51Nod-1257-背包问题 V3
- 51nod 1257 背包问题 V3
- 折半,二分查找问题
- 折半,二分查找问题
- 二分查找小问题
- 经典二分查找问题
- 经典二分查找问题
- 经典二分查找问题
- 经典二分查找问题
- 二分查找问题
- 二分查找引出的问题
- 二分查找问题全集OK
- JZOJ5222【GDOI2018模拟7.12】A(线段树&&二维偏序)
- 【JZOJ100048】紧急撤离
- 垃圾陷阱
- 【生成器】PHP的生成器yield【原创】
- VGA控制的verilog模块设计
- 二分查找,背包问题v3
- 每日一刷——合并有序链表&&求n个数的和
- iOS开发 Runtime使用大全(二)
- Mac OS X 系统配置 Apache+MySql+PHP 详细教程
- 使用GDB在ARM上进行开发调试
- 算法系列——Perfect Squares
- GDOI7.6~7.15模拟总结
- Android常用控件(Widget)
- [bzoj3064]Tyvj 1518 CPU监控 线段树&排行榜垫底留念