K Best

K Best
Time Limit: 8000MS Memory Limit: 65536K
Total Submissions: 6419 Accepted: 1712
Case Time Limit: 2000MS Special Judge

Description

Demy has n jewels. Each of her jewels has some value vi and weight wi.

Since her husband John got broke after recent financial crises, Demy has decided to sell some jewels. She has decided that she would keep k best jewels for herself. She decided to keep such jewels that their specific value is as large as possible. That is, denote the specific value of some set of jewels S = {i1i2, …, ik} as

.

Demy would like to select such k jewels that their specific value is maximal possible. Help her to do so.

Input

The first line of the input file contains n — the number of jewels Demy got, and k — the number of jewels she would like to keep (1 ≤ k ≤ n ≤ 100 000).

The following n lines contain two integer numbers each — vi and wi (0 ≤ vi ≤ 106, 1 ≤ wi ≤ 106, both the sum of all vi and the sum of all wi do not exceed 107).

Output

Output k numbers — the numbers of jewels Demy must keep. If there are several solutions, output any one.

Sample Input

3 2
1 1
1 2
1 3

Sample Output

1 2

Source

Northeastern Europe 2005, Northern Subregion

题意:有n个物品的重量和价值分别是wi和vi。从中选出k个物品使得单位重量的价值最大。输出这k个物品的编号。

分析:在书中看到此题,觉得明显是每个都求出它的单位价值,然后排序找前k个就行。可是{vi,wi} = {{2,2}, (3,5}, {1,2}}这组数据就无法通过,我那种方法是选1号和2号,但答案是选1号和3号。所以那种方法是不行的,也是证明不了的。这题可以用二分来做,设x为k个物品的单位价值,只要找出满足条件x的最大值即可,Sigma{vi}/Sigma{wi} >= x,转化为 Sigma{vi-x*wi} >= 0 因此可以对(vi-x*wi)>=0的值进行排序贪心地进行选取(保证前k个最大,这样直接求和即可知此时的x值是否满足表达式:前k个的和不小于0)。对于用二分寻找x的方法,需要找出所有值或寻求一个表达式(表达式可能需要进行转化),并且表达式的未知数只有一个,且只有单调函数才能进行二分。

code:

[cpp]  view plain  copy
  1. #include<stdio.h>  
  2. #include<math.h>  
  3. #include<algorithm>  
  4. using namespace std;  
  5. int n, k;  
  6. struct P  
  7. {  
  8.     int v, w, num;  
  9.     double y;  
  10.   
  11. }p[100010];  
  12. bool cmp(P c, P d) {return c.y > d.y;}  
  13. bool C(double x) //判断是否满足条件  
  14. {  
  15.     for(int i=0; i<n; i++)  
  16.         p[i].y = p[i].v-x*p[i].w;  
  17.     sort(p,p+n,cmp); //通过结构体排序保存序号  
  18.     double sum = 0;  
  19.     for(int i=0; i<k; i++)  
  20.         sum += p[i].y; //求前k个数的和  
  21.     return sum >= 0;  
  22. }  
  23. int main()  
  24. {  
  25.   
  26.     scanf("%d%d", &n,&k);  
  27.     for(int i=0; i<n; i++)  
  28.     {  
  29.         scanf("%d%d", &p[i].v,&p[i].w);  
  30.         p[i].num = i+1;  
  31.     }  
  32.     double lb = 0, ub = 1e6+10;  
  33.     while(ub-lb >= 1e-8)  
  34.     {  
  35.         double mid = (lb+ub)/2;  
  36.         if(C(mid)) lb = mid;  
  37.         else ub = mid;  
  38.     } //由于最后肯定能求出解,所以数组中的序号也会随之更新,  
  39.     printf("%d", p[0].num);  
  40.     for(int i=1; i<k; i++)   
  41.         printf(" %d", p[i].num);  
  42.     puts("");  
  43.     return 0;  
  44. }  
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
代码解释:format long; close all; clear ; clc tic global B0 bh B1 B2 M N pd=8; %问题维度(决策变量的数量) N=100; % 群 (鲸鱼) 规模 readfile HPpos=chushihua; tmax=300; % 最大迭代次数 (tmax) Wzj=fdifference(HPpos); Convergence_curve = zeros(1,tmax); B = 0.1; for t=1:tmax for i=1:size(HPpos,1)%对每一个个体地多维度进行循环运算 % 更新位置和记忆 % j1=(HPpos(i,:)>=B1);j2=(HPpos(i,:)<=B2); % if (j1+j2)==16 % HPpos(i,:)=HPpos(i,:); %%%%有问题,原算法改正&改进算法映射规则 % else % %HPpos(i,:)=B0+bh.(ones(1,8)(-1)+rand(1,8)2);%产生范围内的随机数更新鲸鱼位置 % HPpos(i,:)=rand(1,8).(B2-B1)+B1; % end HPposFitness=Wzj(:,2M+1); end [~,indx] = min(HPposFitness); Target = HPpos(indx,:); % Target HPO TargetScore =HPposFitness(indx); % Convergence_curve(1)=TargetScore; % Convergence_curve(1)=TargetScore; %nfe = zeros(1,MaxIt); %end % for t=2:tmax c = 1 - t((0.98)/tmax); % Update C Parameter kbest=round(Nc); % Update kbest一种递减机制 % for i = 1:N r1=rand(1,pd)<c; r2=rand; r3=rand(1,pd); idx=(r1==0); z=r2.idx+r3.~idx; % r11=rand(1,dim)<c; % r22=rand; % r33=rand(1,dim); % idx=(r11==0); % z2=r22.idx+r33.~idx; if rand<B xi=mean(HPpos); dist = pdist2(xi,HPpos);%欧几里得距离 [~,idxsortdist]=sort(dist); SI=HPpos(idxsortdist(kbest),:);%距离位置平均值最大的搜索代理被视为猎物 HPpos(i,:) =HPpos(i,:)+0.5((2*(c)z.SI-HPpos(i,:))+(2(1-c)z.xi-HPpos(i,:))); else for j=1:pd rr=-1+2z(j); HPpos(i,j)= 2z(j)cos(2pirr)(Target(j)-HPpos(i,j))+Target(j); end end HPposFitness=Wzj(:,2M+1); % % Update Target if HPposFitness(i)<TargetScore Target = HPpos(i,:); TargetScore = HPposFitness(i); end Convergence_curve(t)=TargetScore; disp(['Iteration: ',num2str(t),' Best Fitness = ',num2str(TargetScore)]); end
05-17
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值