[MOBAN]线性规划-单纯形法模板
一个单纯形解线性规划的板子
UOJ179线性规划
单纯形用于解决一些松弛型的线性规划问题
主要参考(ZhuanZai)fjzzq大神博客和Candy?大神博客
大概就是解决下面这种问题
标准型
$$ 求Max\quad \sum\limits_{j=1}^{n} c_jx_j \ 有限制 s.t.: \ \sum\limits_{j=1}^{n} a_{ij}x_j \le b_i,\ i=1,2,...,m \ x_j \ge 0,\ j=1,2,...,n $$ 对于某些问题可以进行转化。如果限制 $ \sum\limits_{j=1}^{n} a_{ij}x_j = b_i$,那么可以转化为$ \sum\limits_{j=1}^{n} a_{ij}x_j \le b_i $ 和$ \sum\limits_{j=1}^{n} -a_{ij}x_j \le -b_i $两个问题,如果对于某个变量$x$没有非负的限制,那么我们可以把所有关于$x$的式子拆成$x_0$和$x_1$两个变量。 之后要转化为松弛型松弛型
对于松弛变量$x_{n+i} $ $ \sum\limits_{j=1}^{n} a_{ij}x_j \le b_i\ \rightarrow\ x_{n+i}=b_i - \sum\limits_{j=1}^{n} a_{ij}x_j,\ x_{n+i} \ge 0 $ 对于$x_{n+i} $我们称为基变量,而对于别的称为非基变量,我们需要把$ b_i $调整成非负数,否则肯定无解,这样调整之后我们让所有变量都非负,让基变量值为$ b_i $,非基变量为0。 之后单纯形的做法。。。还是认真参考大神的博客吧,大概就是用非基变量替换掉基变量,利用n维度的多边形通过转轴来调整,使得无法通过调整非基变量来进行增大的时候就结束,这时候保证是最大的情况。 对于一些问题求最小,我们可以用对偶原理,转化为标准型。 设原始问题为: 这里的变量都代表矩阵或向量 $ min \ z= c * x $ $ s.t. A * x \le b $ $ x \ge 0 $ 则对偶问题为: $ max \ w = y * b $ $ s.t. \ y * A \ge c $ $ y \ge 0 $ code:#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
typedef double db;
const db eps = 1e-7 , inf = 1e15;
int n,m,type;
db a[55][55];
db ans[55];
int id[55];
void pivot(int l,int e) {
swap(id[n+l],id[e]);
db t = a[l][e]; a[l][e] = 1;
for(int j=0;j<=n;j++) a[l][j]/=t;
for(int i=0;i<=m;i++) if(i!=l&&fabs(a[i][e])>eps) {
t = a[i][e]; a[i][e] = 0;
for(int j=0;j<=n;j++) a[i][j] -= a[l][j]*t;
}
}
bool init() {
while(233) {
int e = 0; int l = 0;
for(int i=1;i<=m;i++) if(a[i][0]<-eps && ( (!l) || (rand()&1) )) l = i;
if(!l) break;
for(int j=1;j<=n;j++) if(a[l][j]<-eps && ( (!e) || (rand()&1) ) ) e = j;
if(!e) { puts("Infeasible"); return 0; }
pivot(l,e);
}
return 1;
}
bool simplex() {
while(233) {
int l = 0 , e = 0; db mn = inf;
for(int j=1;j<=n;j++)
if(a[0][j]>eps) { e=j; break; }
if(!e) break;
for(int i=1;i<=m;i++)
if( a[i][e]>eps && a[i][0]/a[i][e] < mn )
mn = a[i][0]/a[i][e],l=i;
if(!l) { puts("Unbounded"); return false; }
pivot(l,e);
}
return 1;
}
int main() {
srand(233);
scanf("%d%d%d",&n,&m,&type);
for(int i=1;i<=n;i++) {
int x; scanf("%d",&x);
a[0][i] = x;
}
for(int i=1;i<=m;i++) {
for(int j=1;j<=n;j++) {
int x; scanf("%d",&x);
a[i][j] = x;
}
int x; scanf("%d",&x);
a[i][0] = x;
}
for(int i=1;i<=n;i++) id[i] = i;
if(init()&&simplex()) {
printf("%.8lf\n",-a[0][0]);
if(type) {
for(int i=1;i<=m;i++) ans[id[i+n]] = a[i][0];
for(int i=1;i<=n;i++) printf("%.8lf ",ans[i]);
}
}
}