POJ 3111 K Best
Code from http://www.tuicool.com/articles/QfmQvi
Read full article from POJ 3111 K Best 题解 《挑战程序设计竞赛》 � 码农场
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 = {i1, i2, …, ik} as
.
Demy would like to select such k jewels that their specific value is maximal possible. Help her to do so.
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 = {i1, i2, …, ik} as
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).
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.
卖宝救夫:Demy要卖珠宝,n件分别价值vi 重 wi,她希望保留k件使得最大。
思路:给定n个二元组(v,w)保留k个,使得 sigma(v)/sigma(w)的值最大:
http://www.cnblogs.com/tmeteorj/archive/2012/11/05/2754736.html
题意:给定n个结点,每个结点有v,w两个值,求含k个结点的子集,使得sum(v)/sum(w)最大。
题解:0,1分数规划,求g=sum(v)/sum(w)最大,二分枚举g的值,求sum(v-g*w)的最小值,即选出n个结点中v-g*w的最小的k个元素,加起来与0进行比较。0,1分数规划详情请参见OI论文《最小割模型在信息学竞赛中的应用》
int n, k;double s;struct Jewel{ int v, w; int id; bool operator < (const Jewel& other) const { return v - s * w > other.v - s * other.w; }};Jewel jewel[MAX_N];int ids[MAX_N];bool C(double mid){ s = mid; sort(jewel, jewel + n); double total_v = 0, total_w = 0; for (int i = 0; i < k; ++i) // 前k个数计算s { total_v += jewel[i].v; total_w += jewel[i].w; } return total_v / total_w > mid;}///////////////////////////SubMain//////////////////////////////////int main(int argc, char *argv[]){#ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); freopen("out.txt", "w", stdout);#endif cin >> n >> k; double max_s = 0; for (int i = 0; i < n; ++i) { cin >> jewel[i].v >> jewel[i].w; jewel[i].id = i + 1; max_s = max(max_s, (double)jewel[i].v / jewel[i].w); } double lb = 0; double ub = max_s; for (int i = 0; i < 50; ++i) { double mid = (lb + ub) / 2; if (C(mid)) { lb = mid; // 行,说明mid太小 } else { ub = mid; // 不行,说明mid太大 } } for (int i = 0; i < k; ++i) { ids[i] = jewel[i].id; } sort(ids, ids + k); copy(ids, ids + k, ostream_iterator<int>(cout, " ")); #ifndef ONLINE_JUDGE fclose(stdin); fclose(stdout); system("out.txt");#endif return 0;}Code from http://www.tuicool.com/articles/QfmQvi
const int Maxn=100001; const double eps=1e-8; struct node{ int w,v,index; double r; }; node sn[Maxn]; int n,k; bool cmp(node x,node y){ return x.r>y.r; } bool can(double mid) { for(int i=0;i<n;i++) { sn[i].r=sn[i].v-mid*sn[i].w; } //sort(sn,sn+n,cmp); partial_sort(sn,sn+k,sn+n,cmp); double sum=0; for(int i=0;i<k;i++) { sum+=sn[i].r; } return sum>=0; } int main() { while(cin>>n>>k) { int sum=0; for(int i=0;i<n;i++){ scanf("%d %d",&sn[i].v,&sn[i].w); sn[i].index=i+1; sum+=sn[i].v; } double lb=0.0,ub=sum*1.0; while(fabs(ub-lb)>eps) { double mid=(lb+ub)/2; if(can(mid)) lb=mid; else ub=mid; } for(int i=0;i<k-1;i++){ cout<<sn[i].index<<" "; } cout<<sn[k-1].index<<endl; } return 0; }Also check http://www.cnblogs.com/tmeteorj/archive/2012/11/05/2754736.html
Read full article from POJ 3111 K Best 题解 《挑战程序设计竞赛》 � 码农场