基本01分数规划问题
来源
给定n个二元组(value,cost),value是选择此二元组获得的价值(非负),cost是选择此需要的代价,x表示选或者不选(0为不选,1为选),最大化下式:
m
a
x
(
o
r
m
i
n
)
r
=
∑
v
a
l
u
e
i
∗
x
I
c
o
s
t
i
∗
x
i
max(or min) r=\frac{\sum value_i*x_I}{cost_i*x_i}
max(ormin)r=costi∗xi∑valuei∗xI
最大化的方法
首先从图像角度分析下,
设r最大值为
r
∗
r^*
r∗,
r
∗
=
∑
v
a
l
u
e
i
∗
x
I
∑
c
o
s
t
i
∗
x
i
r^*=\frac{\sum value_i*x_I}{\sum cost_i*x_i}
r∗=∑costi∗xi∑valuei∗xI
∑
v
a
l
u
e
i
∗
x
I
−
r
∗
∑
c
o
s
t
i
∗
x
i
=
0
\sum value_i*x_I-r^*\sum cost_i*x_i=0
∑valuei∗xI−r∗∑costi∗xi=0
定义函数
f
(
r
)
=
∑
v
a
l
u
e
i
∗
x
i
−
r
∑
c
o
s
t
i
∗
x
i
=
0
f(r)=\sum value_i*x_i-r\sum cost_i*x_i=0
f(r)=∑valuei∗xi−r∑costi∗xi=0
对于一组固定的x,
f
(
r
)
f(r)
f(r)为一条直线,最大的r值便是横轴截距
二分:
对于上述图像,随机选取一个r,可以分析,若所有固定的x的集合构成的直线中最大的即maxf®>0,则最优值在右边,若小于零则在左边
所以还需要去找r已有的情况下,最大的f(r)
当r,x固定时,化简下
f
(
r
)
f(r)
f(r)
f
(
r
)
=
∑
(
v
a
l
u
e
i
−
r
∗
c
o
s
t
i
)
∗
x
i
f(r)=\sum(value_i-r *cost_i)*x_i
f(r)=∑(valuei−r∗costi)∗xi
也就是找到一组组和使得上式最大,即计算每个物品的
v
a
l
u
e
i
−
r
∗
c
o
s
t
i
value_i-r *cost_i
valuei−r∗costi,排个序就好
wyh的物品
#include<bits/stdc++.h>
using namespace std;
struct node
{
double a;
double b;
double c;
bool operator<(const node& b) const {
return c > b.c;
}
}shu[1000000];
int n,k;
bool judge(double r)
{
double ans=0;
for(int i=0;i<n;i++)
{
shu[i].c=shu[i].b-r*shu[i].a;
}
sort(shu,shu+n);
for(int i=0;i<k;i++)
{
ans+=shu[i].c;
}
return ans>1e-6;
}
int main()
{
int T;
int eps=1e-6;
cin>>T;
while(T--)
{
//初始化应该放在里边!!!!!
double r=1e9,l=1e-6,mid;
cin>>n>>k;
//node *shu=new node[n];
for(int i=0;i<n;i++)
{
cin>>shu[i].a;
cin>>shu[i].b;
}
for(int i=0;i<=100;i++)
{
mid=(r+l)/2.0;
if(judge(mid))
{
l=mid;
}
else
r=mid;
}
//delete []shu;
cout<< fixed << setprecision(2) <<mid<<endl;
}
return 0;
}