作者:jostree 转载请注明出处 http://www.cnblogs.com/jostree/p/4156685.html

使用单纯型法来求解线性规划,输入单纯型法的松弛形式,是一个大矩阵,第一行为目标函数的系数,且最后一个数字为当前轴值下的 z 值。下面每一行代表一个约束,数字代表系数每行最后一个数字代表 b 值。

算法和使用单纯性表求解线性规划相同。

对于线性规划问题:

Max      x1 + 14* x2 + 6*x3

s . t .  x1 + x2 + x3 <= 4

    x1<= 2

    x3 <= 3

    3*x2 + x3 <= 6

    x1,x2,x3 >= 0

我们可以得到其松弛形式:

Max  x1 +  14*x2 + 6*x3
s.t.   x1 +  x2   + x3   + x4 = 4
    x1               + x5 = 2
            x3           + x6 = 3
         3*x2   + x3               + x7 = 6
    x1 , x2 , x3 , x4 , x5 , x6 , x7 ≥ 0

我们可以构造单纯性表,其中最后一行打星的列为轴值。

单纯性表
x1 x2 x3 x4 x5 x6 x7 b
c1=1 c2=14 c3=6 c4=0 c5=0 c6=0 c7=0 -z=0
1 1 1 1 0 0 0 4
1 0 0 0 1 0 0 2
0 0 1 0 0 1 0 3
0 3 1 0 0 0 1 6
      * * * *  

在单纯性表中,我们发现非轴值的x上的系数大于零,因此可以通过增加这些个x的值,来使目标函数增加。我们可以贪心的选择最大的c,再上面的例子中我们选择c2作为新的轴,加入轴集合中,那么谁该出轴呢?

其实我们由于每个x都大于零,对于x2它的增加是有所限制的,如果x2过大,由于其他的限制条件,就会使得其他的x小于零,于是我们应该让x2一直增大,直到有一个其他的x刚好等于0为止,那么这个x就被换出轴。

我们可以发现,对于约束方程1,即第一行约束,x2最大可以为4(4/1),对于约束方程4,x2最大可以为3(6/3),因此x2最大只能为他们之间最小的那个,这样才能保证每个x都大于零。因此使用第4行,来对各行进行高斯行变换,使得二列第四行中的每个x都变成零,也包括c2。这样我们就完成了把x2入轴,x7出轴的过程。变换后的单纯性表为:

单纯性表
x1 x2 x3 x4 x5 x6 x7 b
c1=1 c2=0 c3=1.33 c4=0 c5=0 c6=0 c7=-4.67 -z=-28
1 0 0.67 1 0 0 -0.33 2
1 0 0 0 1 0 0 2
0 0 1 0 0 1 0 3
0 1 0.33 0 0 0 0.33 2
    * * *    

继续计算,我们得到:

单纯性表
x1 x2 x3 x4 x5 x6 x7 b
c1=-1 c2=0 c3=0 c4=0 c5=-2 c6=0 c7=0 -z=-32
1.5 0 1 1.5 0 0 -0.5 3
1 0 0 0 1 0 0 2
0 0 1 0 0 1 0 3
0 1 0.33 0 0 0 0.33 2
    * * *    

此时我们发现,所有非轴的x的系数全部小于零,即增大任何非轴的x值并不能使得目标函数最大,从而得到最优解32.

整个过程代码如下所示:

 #include <cstdio>
#include <climits>
#include <cstdlib>
#include <iostream>
#include <cstring>
#include <vector>
#include <fstream>
#include <set>
using namespace std;
vector<vector<double> > Matrix;
double Z;
set<int> P;
size_t cn, bn; bool Pivot(pair<size_t, size_t> &p)//返回0表示所有的非轴元素都小于0
{
int x = , y = ;
double cmax = -INT_MAX;
vector<double> C = Matrix[];
vector<double> B; for( size_t i = ; i < bn ; i++ )
{
B.push_back(Matrix[i][cn-]);
} for( size_t i = ; i < C.size(); i++ )//在非轴元素中找最大的c
{
if( cmax < C[i] && P.find(i) == P.end())
{
cmax = C[i];
y = i;
}
}
if( cmax < )
{
return ;
} double bmin = INT_MAX;
for( size_t i = ; i < bn ; i++ )
{
double tmp = B[i]/Matrix[i][y];
if( Matrix[i][y] != && bmin > tmp )
{
bmin = tmp;
x = i;
}
} p = make_pair(x, y); for( set<int>::iterator it = P.begin() ; it != P.end() ; it++)
{
if( Matrix[x][*it] != )
{
//cout<<"erase "<<*it<<endl;
P.erase(*it);
break;
}
}
P.insert(y);
//cout<<"add "<<y<<endl;
return true;
} void pnt()
{
for( size_t i = ; i < Matrix.size() ; i++ )
{
for( size_t j = ; j < Matrix[].size() ; j++ )
{
cout<<Matrix[i][j]<<"\t";
}
cout<<endl;
}
cout<<"result z:"<<-Matrix[][cn-]<<endl;
} void Gaussian(pair<size_t, size_t> p)//行变换
{
size_t x = p.first;
size_t y = p.second;
double norm = Matrix[x][y];
for( size_t i = ; i < cn ; i++ )//主行归一化
{
Matrix[x][i] /= norm;
}
for( size_t i = ; i < bn && i != x; i++ )
{
if( Matrix[i][y] != )
{
double tmpnorm = Matrix[i][y];
for( size_t j = ; j < cn ; j++ )
{
Matrix[i][j] = Matrix[i][j] - tmpnorm * Matrix[x][j];
}
}
}
} void solve()
{
pair<size_t, size_t> t;
while()
{ pnt();
if( Pivot(t) == )
{
return;
}
cout<<t.first<<" "<<t.second<<endl;
for( set<int>::iterator it = P.begin(); it != P.end() ; it++ )
{
cout<<*it<<" ";
}
cout<<endl;
Gaussian(t);
}
} int main(int argc, char *argv[])
{
ifstream fin;
fin.open("./test");
fin>>cn>>bn;
for( size_t i = ; i < bn ; i++ )
{
vector<double> vectmp;
for( size_t j = ; j < cn ; j++)
{
double tmp = ;
fin>>tmp;
vectmp.push_back(tmp);
}
Matrix.push_back(vectmp);
} for( size_t i = ; i < bn- ; i++ )
{
P.insert(cn-i-);
}
solve();
}
/////////////////////////////////////
//glpk input:
///* Variables */
//var x1 >= 0;
//var x2 >= 0;
//var x3 >= 0;
///* Object function */
//maximize z: x1 + 14*x2 + 6*x3;
///* Constrains */
//s.t. con1: x1 + x2 + x3 <= 4;
//s.t. con2: x1 <= 2;
//s.t. con3: x3 <= 3;
//s.t. con4: 3*x2 + x3 <= 6;
//end;
/////////////////////////////////////
//myinput:
//8 5
//1 14 6 0 0 0 0 0
//1 1 1 1 0 0 0 4
//1 0 0 0 1 0 0 2
//0 0 1 0 0 1 0 3
//0 3 1 0 0 0 1 6
/////////////////////////////////////

单纯形法C++实现的更多相关文章

  1. BZOJ 1061: [Noi2008]志愿者招募 [单纯形法]【学习笔记】

    1061: [Noi2008]志愿者招募 Time Limit: 20 Sec  Memory Limit: 162 MBSubmit: 3975  Solved: 2421[Submit][Stat ...

  2. BZOJ 1061: [Noi2008]志愿者招募 [单纯形法]

    传送门 题意: 长为$n$的序列,第$i$位至少$b_i$,$m$种区间使$[l_i,r_i]+1$代价为$a_i$ 求满足的最小花费 复习单纯形法重做一遍 原始问题$m$个变量$n$个约束,$a_{ ...

  3. 智能优化 之 下山单纯形法 C++

    单纯形法简介在其他网站上都可以查到,我就不多说了 我们主要说方法 它主要解决的是局部最优解的问题 利用多边形进行求解的,若有n个变量,则利用n+1边形 我们这里以两个变量为例,求解第三维度的最优解 例 ...

  4. 单纯形法MATALAB实现

    参考单纯形法的步骤,MATALAB中的实现如下(求极小值): 注:对于极大值的求解,只需要对目标函数添加负号,求解出来的\(X\),再带入原目标函数即可. function [ X, z ] = si ...

  5. BZOJ 1061: [Noi2008]志愿者招募 [单纯形法]【学习笔记看另一篇吧】

    1061: [Noi2008]志愿者招募 Time Limit: 20 Sec  Memory Limit: 162 MBSubmit: 3975  Solved: 2421[Submit][Stat ...

  6. 能用的单纯形法python代码

    网上找了一些代码,发现有一些是不能用的,出现错误说集合为空 1.网上出现了好多次,但是不能用的,只能部分模型能用,比如例子中所示 原链接:https://www.jianshu.com/p/b233c ...

  7. POJ1275 Cashier Employment[差分约束系统 || 单纯形法]

    Cashier Employment Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 7997   Accepted: 305 ...

  8. BZOJ 3112: [Zjoi2013]防守战线 [单纯形法]

    题目描述 战线可以看作一个长度为n 的序列,现在需要在这个序列上建塔来防守敌兵,在序列第i 号位置上建一座塔有Ci 的花费,且一个位置可以建任意多的塔,费用累加计算.有m 个区间[L1, R1], [ ...

  9. BZOJ 3550: [ONTAK2010]Vacation [单纯形法]

    有3N个数,你需要选出一些数,首先保证任意长度为N的区间中选出的数的个数<=K个,其次要保证选出的数的个数最大. 好像都是费用流... 单纯性裸题呀... 注意每个数最多选1次 #include ...

随机推荐

  1. node.js小工具--修改Xcode 'Create by'作者名称

    简介 用Xcode创建源文件时会自动在文件开始位置加入如下注释: // // ISSImageCycleScrollView.m // SoftTravel // // Created by iss1 ...

  2. Linux下的简单好用的计算器bc

    1. 关于bc bc是随意精度计算器语言,通常在linux下当计算器用,简单好用.相当于windows下的计算器. 2. 支持的运算符 主要的数学运算: + 加法 - 减法 * 乘法 / 除法 ^ 指 ...

  3. ant脚本打jar包 自动获取时间以及项目svn版本号

    1.关键代码,获取时间 <tstamp> <format property="touch.time" pattern="yyyy/MM/dd hh:mm ...

  4. LVS 详解

    http://zh.linuxvirtualserver.org/node/25 http://chrinux.blog.51cto.com/6466723/1198748 http://www.cn ...

  5. Ruby on Rails Tutorial 第二章 之 toy_app项目搭建

    (第一章小结) 第一步:生成项目骨架 $ rails _4.1.6_ new toy_app 第二步:修改Gemfile 第三步:安装gem $ bundle install --without pr ...

  6. IP101A芯片默认物理地址(PHY Adress)确定

    转载:http://blog.csdn.net/ropai/article/details/6961157 根据IP101A的DataSheet,芯片的第9,10,12,13,15脚为PHYAD0~P ...

  7. 琐碎-关于hadoop2.X那些端口

    此文转载http://www.aboutyun.com/thread-7513-1-1.html Hadoop集群的各部分一般都会使用到多个端口,有些是daemon之间进行交互之用,有些是用于RPC访 ...

  8. iOS H5容器的一些探究(一):UIWebView和WKWebView的比较和选择

    一.Native开发中为什么需要H5容器 Native开发原生应用是手机操作系统厂商(目前主要是苹果的iOS和google的Android)对外界提供的标准化的开发模式,他们对于native开发提供了 ...

  9. Cable master

    Description Inhabitants of the Wonderland have decided to hold a regional programming contest. The J ...

  10. Java中数组的快排

    描述输入三个字符(可以重复)后,按各字符的ASCII码从小到大的顺序输出这三个字符.   输入 第一行输入一个数N,表示有N组测试数据.后面的N行输入多组数据,每组输入数据都是占一行,有三个字符组成, ...