# 线性规划学习笔记
由于时间的原因,线性规划并没有学明白... 在这一方面我的能力属实有限,先整个链接吧...
参考资料:
0. 运筹学
1. 线性规划之单纯性算法
2. 单纯性算法
3. 线性规划
4. 线性规划
5. 对偶理论
6. 线性规划的对偶问题
7. 单纯形法
# P3980 [NOI2008] 志愿者招募
# 题目描述
有一个需要 天完成的项目,第 天至少需要 人。一共有 类志愿者可以招募,第 类志愿者可以从第 天工作到 天,招募的费用是每人 元。请设计一种方案使其满足在招募到足够的志愿者的前提下,招募费用最少(当然不需要输出方案)。
#
记 为需要的第 类的志愿者的人数, 为第 天第 类志愿者能否工作。
可以得到如下式子:
所需费用 。
线性规划的对偶定理
原问题:
对偶问题:
我们对这题的式子套一下上面的变换:
原问题:
对偶问题:
于是我们就将一个最小化型线性规划转化为了标准形式(最大化型线性规划)。
都为非负整数,所以转化后的线性规划就有了基本解,那么就可以用单纯性算法(单纯形法)求取最优解。
贴个代码跑路了
#define Meteorshower_Y true | |
#include<iostream> | |
#include<climits> | |
#include<cstdio> | |
using namespace std; | |
const double inf = 1e-6; | |
const int MAXN = 1e3+10; | |
const int MAXM = 1e4+10; | |
const int MAXA = MAXN+MAXM; | |
auto simplex() -> double; | |
auto pivot(int r, int c) -> void; | |
int n, m, a[MAXN]; | |
int s[MAXM], t[MAXM], c[MAXM]; | |
double A[MAXM][MAXN], ans; | |
auto main() -> signed | |
{ | |
scanf("%d%d", &n, &m); | |
for(int j = 1; j <= n; j += 1) | |
scanf("%d", &a[j]); | |
for(int i = 1; i <= m; i += 1) | |
scanf("%d%d%d", &s[i], &t[i], &c[i]); | |
for(int i = 1; i <= m; i += 1) | |
for(int j = s[i]; j <= t[i]; j += 1) | |
A[i][j] = 1; | |
printf("%0.lf", -simplex()); | |
return 0; | |
} | |
auto simplex() -> double | |
{ | |
while(Meteorshower_Y) | |
{ | |
int basic = 0, notbasic = 0; | |
double mina = 1e16; | |
for(int j = 1; j <= n; j += 1) | |
if(a[j] > a[notbasic]) notbasic = j; | |
if(!notbasic) return ans; | |
for(int i = 1; i <= m; i += 1) | |
if(A[i][notbasic] > inf and mina > c[i]/A[i][notbasic]) | |
basic = i, mina = c[i]/A[i][notbasic]; | |
if(!basic) return 1e16; | |
pivot(basic, notbasic); | |
} | |
return ans; | |
} | |
auto pivot(int R, int C) -> void | |
{ | |
double cyr = 1.0/A[R][C]; | |
A[R][C] = 1; | |
for(int j = 1; j <= n; j += 1) A[R][j] *= cyr; | |
c[R] *= cyr; | |
cyr = a[C]; a[C] = 0; | |
for(int j = 1; j <= n; j += 1) a[j] -= cyr*A[R][j]; | |
ans -= cyr*c[R]; | |
for(int i = 1; i <= m; i += 1) | |
{ | |
if(i == R) continue; | |
cyr = A[i][C]; A[i][C] = 0; | |
for(int j = 1; j <= n; j += 1) A[i][j] -= cyr*A[R][j]; | |
c[i] -= cyr*c[R]; | |
} | |
} |