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;
}