01分数规划 :01即取还是不取,分数即所求型式为,规划就是选取最好的方案。
一般情况题目给出n个物品,再给出每个物品的价值以及物重,选取k个物品,问你在所有可能选取的方案中,最大的单位价值为多少(单位价值为选取的 k 个物品的总价值和总重量的比值)。
我们选择采用二分法,进行判断。我们要求的是选取的 k 个物品的总价值和总重量的比值最大,最终求得是。
所以我们在可取的区间内每次取区间中值mid,判断是否符合,符合则可以取右边区间,不符合则取左区间。
eg:
int l = 0, r = 1e8 + 5;
while (l <= r)
{
int mid = (l + r) / 2;
if (judge(mid)) l = mid + 1;
else r = mid - 1;
}
接下来是要写判断函数judge
我们知道我们所取的mid要符合 >=mid,则(a-b*mid)>=0。所以我们要从大到小取
a-b*mid来相加直到k个才能保证最有可能大于等于0.
eg:
bool comp(node a,node b)//从大到小排序
{
return a.tmp > b.tmp;
}
int judge(double x)
{
for (int i = 1; i <= n; i++)
{
a[i].tmp = a[i].v*1.0 - x * a[i].w*1.0;储存每个物品的价值-x*重量值
}
sort(a + 1, a + 1 + n, comp);//进行排序
double sum = 0;
for (int i = 1; i <= k; i++)//求和
{
sum += a[i].tmp;
}
return sum >= 0.0;//返回是否大于等于0
}
例题1:
题目描述
wyh学长现在手里有 nnn 个物品,这 nnn 个物品的重量和价值都告诉你,然后现在让你从中选取 kkk 个,问你在所有可能选取的方案中,最大的单位价值为多少(单位价值为选取的 kkk 个物品的总价值和总重量的比值)
输入描述:
输入第一行一个整数 T(1≤T≤10) 接下来有 T 组测试数据,对于每组测试数据,第一行输入两个数 n 和 k(1≤k≤n≤100000)k 接下来有 n 行,每行两个是 a 和 b (0<a,b≤1000000)代表这个物品的重量和价值
输出描述:
对于每组测试数据,输出对应答案,结果保留两位小数
示例1
输入
1 3 2 2 2 5 3 2 1
输出
0.75
说明
对于样例来说,我们选择第一个物品和第三个物品,达到最优目的
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
struct node
{
double w, v,tmp;
}a[100010];
int n, k;
bool comp(node a,node b)//从大到小排序
{
return a.tmp > b.tmp;
}
int judge(double x)
{
for (int i = 1; i <= n; i++)
{
a[i].tmp = a[i].v*1.0 - x * a[i].w*1.0;//存储价值-x*重量
}
sort(a + 1, a + 1 + n, comp);//排序
double sum = 0;
for (int i = 1; i <= k; i++)//求和
{
sum += a[i].tmp;
}
return sum >= 0.0;返回是否大于等于0
}
int main()
{
int t;
cin >> t;
while (t--)
{
cin >> n >> k;
for (int i = 1; i <= n; i++)
{
cin >> a[i].w >> a[i].v;
}
double l = 1.0, r = 1e7 + 10;
double ans;
for(int i=1;i<=100;i++)
{
double mid = (l + r) / 2;
if (judge(mid)) l = mid+1;
else r = mid-1;
}
printf("%.2lf\n", l-1);
}
}
例题2:
题目描述
小咪是一个土豪手办狂魔,这次他去了一家店,发现了好多好多(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
#include<iostream>
#include<algorithm>
using namespace std;
int t;
int n, k;
struct node
{
int c;
int v;
long long sum;
}a[10005];
bool cmp(node a, node b)
{
return a.sum > b.sum;
}
int judge(long long x)
{
for (int i = 1; i <= n; i++)
{
a[i].sum = a[i].v - x * a[i].c;
}
sort(a + 1, a + 1 + n, cmp);
long long num = 0;
for (int i = 1; i <= k; i++)
{
num += a[i].sum;
}
if (num >= 0) return 1;
else return 0;
}
int main()
{
cin >> t;
while (t--)
{
cin >> n >> k;
for (int i = 1; i <= n; i++)
{
cin>>a[i].c>>a[i].v;
}
int l = 0;
int r = 1e8 + 5;
while (l <= r)
{
int mid = (l + r) / 2;
if (judge(mid)) l = mid + 1;
else r = mid - 1;
}
cout << l-1 << endl;
}
return 0;
}
很明显懂了以后,遇到这种题目就可以选择直接套用模板。