01分数规划 基础教学篇

01规划问题大概是给你n件物品,每个物品有价值P和体积V两个属性,让你选择其中k件,使得这k件物品的价值和除以体积和最大。

我们可以设X[i]=0/1,如果X[i]==0说明第i件物品物品不选,如果X[i]==1说明第i件物品要选。

那么我们要求的k件物品的价值和除以体积和R=sigma(P[i]*X[i])/sigma(V[i]*X[i]);

我们再定义一个函数f(L)=sigma(P[i]*X[i])-L*sigma(V[i]*X[i])=sigma((P[i]-L*V[i])*X[i]);设d[i]=P[i]-L*V[i];则f(L)=sigma(d[i]*X[i]);

假设f(L)>0,也就是sigma(P[i]*X[i])-L*sigma(V[i]*X[i])>0,变形后就是sigma(P[i]*X[i])/sigma(V[i]*X[i])>L,那么01分数规划问题就可以转化为找到最大的L使得f(L)>0;

由于d[i]=P[i]-L*V[i]是随着L增大而递减的,因此f(L)=sigma(d[i]*X[i])也是线性的,可以直接二分寻找这个L。

那么如何判断f(L)>0呢?我们处理出来d数组后,要在里面选择其中k个使得他们的和大于0,那么就要找前k大的数字加起来,所以排下序再记录下和就行了。

找到L后,L也是我们所要求的答案。

这里有道模板题: http://poj.org/problem?id=2976

参考代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <string>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#define b first
#define a second
#define clr(u,v); memset(u,v,sizeof(u));
#define in() freopen("data","r",stdin);
#define out() freopen("ans","w",stdout);
#define Clear(Q); while (!Q.empty()) Q.pop();
#define pb push_back
using namespace std;
typedef long long ll;
typedef pair<double, double> pdd;
typedef pair<int, int> pii;
const int maxn = 1e4 + 10;
const int INF = 0x3f3f3f3f;
const double eps = 1e-6;
pdd N[maxn];
int n, k;
double d[maxn];
bool f(double L)
{
    double sum = 0;
    for (int i = 0; i < n; i++)
        d[i] = N[i].a - L * N[i].b;
    sort(d, d + n);
    for (int i = n - 1; i >= n - k; i--)
        sum += d[i];
    return sum > 0;
}

double solve(double L, double R)
{
    double mid;
    while (R - L > eps)
    {
        mid = (L + R) / 2;
        if (f(mid)) L = mid;
        else R = mid;
    }
    return mid;
}

int main()
{
    while(scanf("%d%d", &n, &k), n || k)
    {
        double Mx = 0;
        k = n - k;
        for (int i = 0; i < n; i++) scanf("%lf", &N[i].a);
        for (int i = 0; i < n; i++)
        {
            scanf("%lf", &N[i].b);
            Mx = max(Mx, N[i].a / N[i].b);
        }
        printf("%.0f\n", solve(0, Mx) * 100);
    }
    return 0;
}

 

posted @ 2017-02-15 17:34  酱油党gsh  阅读(164)  评论(0编辑  收藏  举报