码迷,mamicode.com
首页 > 其他好文 > 详细

K Besk [POJ 3111]

时间:2017-10-11 19:20:58      阅读:183      评论:0      收藏:0      [点我收藏+]

标签:决定   技术   one   描述   ack   return   pen   珠宝   struct   

描述
  Demy有n颗宝石。她的每个珠宝都有一些价值vi和重量wi。自从丈夫约翰在最近的金融危机爆发后,已经决定出售一些珠宝。她决定自己会保留最好的珠宝。她决定保留这样的宝石,使他们的具体价值尽可能大。也就是说,表示某组宝石S = {i1,i2,...,ik}的具体值。
  Demy想选择这样的k宝石,他们的具体值是最大可能的。帮助她这样做。

输入
  输入文件的第一行包含n - Demy得到的珠宝数量,k - 她想保留的珠宝数量(1≤k≤n≤100 000)。
  以下n行包含两个整数,每个-vi和wi(0≤vi≤10e6,1≤wi≤10e6,所有vi的和和全部wi之和不超过10e7)。

输出
  输出k个数字 - 戴姆必须保留的珠宝数量。如果有几个解决方案,输出任何一个。

样例输入
3 2
1 1
1 2
1 3

样例输出

1 2

题目大意:
n个珠宝,每个珠宝对应一个重量wi和价值vi,现在要从中找出k个,使的这k个珠宝的单位重量的价值最大,输出这k个珠宝的编号。

解题思路:
首先,我们给出一个贪心思路:计算出每个珠宝的单位价值,从大到小选择k个,这个贪心思路是显然错误的。感性证明:单位价值只体现了比值,在数值大小不一样的时候,比值不可做加法。
所以,我们来换一个角度:
我们设一个集合S的单位价值≥x
则有
∑vi / ∑wi ≥ x (i∈S)
变形得
∑(vi - x × wi )≥0(i∈S)
所以,对vi-x×wi排序,选择前k个,检验是否≥0
而x我们可以通过二分来枚举

Code

技术分享
 1 #include<set>
 2 #include<map>
 3 #include<cmath>
 4 #include<queue>
 5 #include<stack>
 6 #include<cstdio>
 7 #include<cstring>
 8 #include<iostream>
 9 #include<algorithm>
10 #define RG register int
11 #define ll long long
12 #define inf (1<<30)
13 #define eps (1e-15)
14 #define maxn 100005
15 #define rep(i,a,b) for(RG i=a;i<=b;i++)
16 #define per(i,a,b) for(RG i=a;i>=b;i--)
17 using namespace std;
18 int n,k;
19 struct Dat{
20     double v,w;
21 }dat[maxn];
22 double tmp[maxn];
23 inline int read()
24 {
25     int x=0,f=1;char c=getchar();
26     while(c<0||c>9){if(c==-)f=-1;c=getchar();}
27     while(c>=0&&c<=9){x=x*10+c-0;c=getchar();}
28     return x*f;
29 }
30 
31 inline bool cmp(const double &a,const double &b)
32 {
33     return a>b;
34 }
35 
36 inline bool judge(double x)
37 {
38     rep(i,1,n)    tmp[i]=dat[i].v-x*dat[i].w;
39     sort(tmp+1,tmp+1+n,cmp);
40     double sum=0;
41     rep(i,1,k)    sum+=tmp[i];
42     return sum>=0;
43 }
44 
45 struct Ans{
46     int id;
47     double val;
48 }ans[maxn];
49 
50 inline bool cmp2(const Ans &a,const Ans &b)
51 {
52     return a.val>b.val;
53 }
54 
55 inline void work(double x)
56 {
57     rep(i,1,n)    ans[i].id=i,ans[i].val=dat[i].v-x*dat[i].w;
58     sort(ans+1,ans+1+n,cmp2);
59     rep(i,1,k) printf("%d ",ans[i].id);
60 }
61 
62 void solve()
63 {
64     double l=0,r=inf;
65     rep(i,1,50)
66     {
67         double mid=(l+r)/2;
68         if(judge(mid))    l=mid;
69         else r=mid;
70     }
71     work(r);
72 }
73 
74 int main()
75 {
76     n=read(),k=read();
77     rep(i,1,n)    dat[i].v=read(),dat[i].w=read();
78     solve();
79     return 0;
80 }
点击展开代码

 

K Besk [POJ 3111]

标签:决定   技术   one   描述   ack   return   pen   珠宝   struct   

原文地址:http://www.cnblogs.com/ibilllee/p/7651952.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!