2017年浙江工业大学大学生程序设计迎新赛预赛E 最大化平均值
2018-02-08 11:13
316 查看
链接:https://www.nowcoder.net/acm/contest/52/E
来源:牛客网
题目描述
小咪是一个土豪手办狂魔,这次他去了一家店,发现了好多好多(n个)手办,但他是一个很怪的人,每次只想买k个手办,而且他要让他花的每一分钱都物超所值,即:买下来的东西的总价值/总花费=max。请你来看看,他会买哪些东西吧。
输入描述:
多组数据。
第一行一个整数T,为数据组数。
接下来有T组数据。
对于每组数据,第一行两个正整数n,k,如题。
接下来n行,每行有两个正整数ci,vi。分别为手办的花费和它对于小咪的价值。
输出描述:
对于每组数据,输出一个数,即能得到的总价值/总花费的最大值。精确至整数。
示例1
输入
1
5 1
1 2
2 3
3 4
4 5
5 6
输出
2
备注:
1≤T≤10
1≤n≤104
1≤k≤n
1≤ci,vi≤104
大化平均值的经典,一般最先想到可能的方法是按照单位价值排序,从大到小的进行选取,但是这个方法对于下面一组例子来说:
n=3; k=2; (w,v)=(2,2),(5,3),(2,1);则可能得出的结果是5/7=0.714,所以这个方法是要排除的,那么如何想到最大化平均值这个方向呢?实际上,对于这个问题我们可以使用二分搜索法解决,我们定义:
条件get(mid):=可以选择使得单位重量的价值不小于mid
因此,原问题就变成了求满足get(mid)的最大mid,那么如何判断get(mid)是否可行?假设我们选了某个物品的集合S()那么它们的单位重量的价值是;定义sum(v)为v的值的和
sum(Vi(i属于S))/sum(Wi(i属于S));因此就变成了判断是否存在mid满足以下条件:sum(Vi(i属于S))/sum(Wi(i属于S))>=mid;变形得到:sum(Vi-mid*Wi)>=0,因此对此式的值进行贪心选取,进一步求sum(Vi-mid*Wi)从大到小排列中前k个的和不小于零,每次判断的复杂度为O(n*log(n))
来源:牛客网
题目描述
小咪是一个土豪手办狂魔,这次他去了一家店,发现了好多好多(n个)手办,但他是一个很怪的人,每次只想买k个手办,而且他要让他花的每一分钱都物超所值,即:买下来的东西的总价值/总花费=max。请你来看看,他会买哪些东西吧。
输入描述:
多组数据。
第一行一个整数T,为数据组数。
接下来有T组数据。
对于每组数据,第一行两个正整数n,k,如题。
接下来n行,每行有两个正整数ci,vi。分别为手办的花费和它对于小咪的价值。
输出描述:
对于每组数据,输出一个数,即能得到的总价值/总花费的最大值。精确至整数。
示例1
输入
1
5 1
1 2
2 3
3 4
4 5
5 6
输出
2
备注:
1≤T≤10
1≤n≤104
1≤k≤n
1≤ci,vi≤104
大化平均值的经典,一般最先想到可能的方法是按照单位价值排序,从大到小的进行选取,但是这个方法对于下面一组例子来说:
n=3; k=2; (w,v)=(2,2),(5,3),(2,1);则可能得出的结果是5/7=0.714,所以这个方法是要排除的,那么如何想到最大化平均值这个方向呢?实际上,对于这个问题我们可以使用二分搜索法解决,我们定义:
条件get(mid):=可以选择使得单位重量的价值不小于mid
因此,原问题就变成了求满足get(mid)的最大mid,那么如何判断get(mid)是否可行?假设我们选了某个物品的集合S()那么它们的单位重量的价值是;定义sum(v)为v的值的和
sum(Vi(i属于S))/sum(Wi(i属于S));因此就变成了判断是否存在mid满足以下条件:sum(Vi(i属于S))/sum(Wi(i属于S))>=mid;变形得到:sum(Vi-mid*Wi)>=0,因此对此式的值进行贪心选取,进一步求sum(Vi-mid*Wi)从大到小排列中前k个的和不小于零,每次判断的复杂度为O(n*log(n))
#include<iostream> #include<cstdio> #include<algorithm> using namespace std; #define N 10005 int w ,v ; long long c ; int check(int x); int T,n,k,left,right,mid,ans; int main() { scanf("%d",&T); while(T--) { scanf("%d%d",&n,&k); for(int i = 1;i<=n;i++) scanf("%d%d",&w[i],&v[i]); int left = 0, right = 10000;// 注意left应从0开始,从1开始将会漏掉一些情况 while(left<=right)//注意二分法查找的条件必须有等于号 { int mid = (left+right)/2; if(check(mid)) { ans = mid; left = mid + 1; } else right = mid -1; } printf("%d\n",ans); } return 0; } int check(int x)//条件C(x)为可以选择使得单位重量的价值不小于x,注意是大于或等于x,返回值为sum>=0 { for(int i=1;i<=n;i++) c[i] = v[i]-w[i]*x;//记住公式 sort(c+1,c+1+n);//正序排列 long long sum = 0; for(int i=n;i>n-k;i--)//注意写法 sum +=c[i]; return sum>=0; }
相关文章推荐
- 2017年浙江工业大学大学生程序设计迎新赛预赛 J 裁缝大师【简单几何】
- 2017年浙江工业大学大学生程序设计迎新赛预赛
- 2017年浙江工业大学大学生程序设计迎新赛预赛
- 2017年浙江工业大学大学生程序设计迎新赛预赛
- 2017年浙江工业大学大学生程序设计迎新赛热身赛
- nowcoder 2017年浙江工业大学大学生程序设计迎新赛预赛- CC的神奇背包
- 2017年浙江工业大学大学生程序设计迎新赛热身赛 I after与迷宫 牛客
- 2017年浙江工业大学大学生程序设计迎新赛热身赛-E:递推(矩阵快速幂)
- 2017年浙江工业大学大学生程序设计迎新赛预赛-K:栗酱的连通图(最大生成树)
- nowcoder 2017年浙江工业大学大学生程序设计迎新赛预赛-栗酱的异或和
- 2017年浙江工业大学大学生程序设计迎新赛预赛A【巴什博奕 异或和】
- 2017年浙江工业大学大学生程序设计迎新赛热身赛-J-Forever97与寄信
- 2017年浙江工业大学大学生程序设计迎新赛预赛 I 【简单题】
- 2017年浙江工业大学大学生程序设计迎新赛预赛 J【三角函数的应用】
- 【牛客网】2017年浙江工业大学大学生程序设计迎新赛热身赛 F题 方块 I【证明题】【想法题】
- 2017年浙江工业大学大学生程序设计迎新赛预赛 D 简单的数据结构【纯 stl -> List 的应用】
- 2017年浙江工业大学大学生程序设计迎新赛预赛 K 【看似是图其实是贪心】
- 2017年浙江工业大学大学生程序设计迎新赛预赛 L【简单题】
- 2017年浙江工业大学大学生程序设计迎新赛热身赛 部分题解
- 2017年浙江工业大学大学生程序设计迎新赛预赛 H - 栗酱的文明