[BZOJ 1061][Noi2008]志愿者招募

来源:互联网 发布:2017网络自制综艺现状 编辑:程序博客网 时间:2024/04/30 14:30

Description

申奥成功后,布布经过不懈努力,终于成为奥组委下属公司人力资源部门的主管。布布刚上任就遇到了一个难题:为即将启动的奥运新项目招募一批短期志愿者。经过估算,这个项目需要N 天才能完成,其中第i 天至少需要Ai 个人。 布布通过了解得知,一共有M 类志愿者可以招募。其中第i 类可以从第Si 天工作到第Ti 天,招募费用是每人Ci 元。新官上任三把火,为了出色地完成自己的工作,布布希望用尽量少的费用招募足够的志愿者,但这并不是他的特长!于是布布找到了你,希望你帮他设计一种最优的招募方案。

Input

第一行包含两个整数N, M,表示完成项目的天数和可以招募的志愿者的种类。 接下来的一行中包含N 个非负整数,表示每天至少需要的志愿者人数。 接下来的M 行中每行包含三个整数Si, Ti, Ci,含义如上文所述。为了方便起见,我们可以认为每类志愿者的数量都是无限多的。

Output

仅包含一个整数,表示你所设计的最优方案的总费用。

Solution

设每类志愿者招募了xi名
按照每天的约束来列不等式,表示第i天>=ci
最小化费用
可是我们发现0并不是一个初始解
对偶一下
变成最大化费用。<=
单纯形即可

#include <bits/stdc++.h>using namespace std;int n, m;const double inf = 1e12;struct solver{    double a[10010][1010], b[10010], c[1010], v;    void Debug(){        printf("Max : ");        for(int i = 1; i <= n; i ++)            printf("%.2lf ", c[i]);        printf("%.2lf\n", v);        for(int i = 1; i <= m; i ++){            for(int j = 1; j <= n; j ++)                printf("%.2lf ", a[i][j]);            printf("%.2lf\n", b[i]);        }        system("pause");    }    void pivot(int f, int e){        b[f] /= a[f][e];        for(int i = 1; i <= n; i ++)            if(i != e)a[f][i] /= a[f][e];        a[f][e] = 1 / a[f][e];        for(int i = 1; i <= m; i ++){            if(i == f || a[i][e] == 0)continue;            b[i] -= a[i][e] * b[f];            for(int j = 1; j <= n; j ++)                if(j != e)a[i][j] -= a[i][e] * a[f][j];            a[i][e] = -a[i][e] * a[f][e];        }        v += c[e] * b[f];        for(int i = 1; i <= n; i ++)            if(i != e)c[i] -= c[e] * a[f][i];        c[e] = -c[e] * a[f][e];    }    double solve(){        int e, i, f;        while(true){            for(e = 0, i = 1; i <= n; i ++)                if(c[i] > 0){e = i; break;}            if(e == 0)return v;            double lim = inf;            for(i = 1; i <= m; i ++){                if(a[i][e] > 0 && lim > b[i] / a[i][e]){                    lim = b[i] / a[i][e];                    f = i;                }            }            pivot(f, e);        }    }}spx;int main(){    scanf("%d%d", &n, &m);    int l, r, x;    for(int i = 1; i <= n; i ++){        scanf("%d", &x);        spx.c[i] = x;    }    for(int i = 1; i <= m; i ++){        scanf("%d%d", &l, &r);        for(int j = l; j <= r; j ++)            spx.a[i][j] = 1;        scanf("%d", &x);        spx.b[i] = x;    }    printf("%d", (int)(spx.solve() + 0.1));    return 0;}
0 0