作者: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. ios开发——常用经典算法OC篇&冒泡/快速

    冒泡排序与快速排序 1.序言 ios开发中涉及到算法的地方还真不多,除非你的应用程序真的非常大,或者你想你的应用程序性能非常好才会去想到关于算法方面的性能优化,而在ios开发中真的能用得到的也就是关于 ...

  2. gulp如何自定义插件

    gulp是基于”流“的构建工具,上层流的输出就是下层流的输入,为了更好的支持链式操作,可以使用through2或者map-stream这两个库来对node stream做一层包装 这里,我们就使用th ...

  3. AS3 Signals

    在项目中,使用as3内置事件框架必须通过自定义事件才可以实现值的传递,大量自定义事件.定义常量和整个事件派发的管理.添加侦听器.移除侦听器,或多或少都会带来大量的代码,而signals这个框架思想原来 ...

  4. MySQL · BUG分析 · Rename table 死锁分析

    http://mysql.taobao.org/monthly/2016/03/06/ 背景 InnoDB buffer pool中的page管理牵涉到两个链表,一个是lru链表,一个是flush 脏 ...

  5. 有符号的范围,-128~+127详解(zt)

    这是一个困惑了我几年的问题,它让我对现在的教科书和老师极其不满,从我N年前开始摸电脑时,就几乎在每一本C++教科书上都说,8位有符号的取值范围是-128~+127,为什么不是-127~+127呢,后来 ...

  6. windows系统中eclipse C c++开发环境的搭建

    搜索了网上各种版本的eclipse c,c++ ,头都晕了..以前的版本很多都失效了..下面这个是搞了两天才调通的.超级强大,推荐 1.先装MinGW 2.配置环境变量3.然后把安装目录\mingw\ ...

  7. Integer的缓存和自动拆装箱

    先看一个简单的例子: public class TestInteger { public static void main(String[] args) { System.out.println(&q ...

  8. 装饰者模式--《Head First DesignPattern》

    装饰者模式动态地将责任附加到对象杭,若要拓展功能,装设置提供了比继承更有弹性的替代方案. 星巴兹有多种咖啡,它们具有不同的价格.在购买咖啡时,也可以要求在其中加入各种调料,例如豆浆.摩卡.奶泡等等.需 ...

  9. APK文件安装模拟器和ADB命令的使用

    1.安装APK文件到模拟器 Android手机使用的执行文件为APK格式,类似于Windows平台的exe文件.在Android模拟器中安装APK文件有多种方法,如果你是开发人员,可以通过Eclips ...

  10. 最短路径之Dijkstra算法及实例分析

    Dijkstra算法迪科斯彻算法 Dijkstra算法描述为:假设用带权邻接矩阵来表示带权有向图.首先引进一个辅助向量D,它的每个分量D[i]表示当前所找到的从始点v到每个终点Vi的最短路径.它的初始 ...