一、线性规划的标准化
(1)目标函数:max
(2)约束条件:等式
(3)变量约束:非负xj >= 0
(4)资源限量:非负bj >= 0
二、非标准型的标准化(以下变量后面括号中均为下标)
(1)min转换为max
min Z = CX ---> max Z = -CX
(2)不等式转换为等式约束
∑a( i,j )x( j ) <= b( i ) ------> ∑a( i,j ) x( j ) + x( n+1 ) = b( i ) x( n+1 )为松弛变量
∑a( i,j )x( j ) >= b( i ) ------> ∑a( i,j ) x( j ) - x( n+1 ) = b( i ) x( n+1 )为松弛变量
(3)变量约束转换
若x( j ) <= 0,x( j ) = - x( j_ ), 则x( j_ ) >= 0;
若x( j )无限制,令x( j_ ) >= 0, x( j__ ) >= 0, 则x( j ) = x( j_ )-x( j__ );
若a <= x( j ) <= b,令x( j_ ) = x( j )-a,则x( j_ ) >= 0,
x( j_ ) <= b-a,这样就变成不等式约束了,即为x( j_ )+x( j__ ) <= b-a,x( j__ ) >= 0。
(4)把b( i ) <= 0转换成b( i ) >= 0
只需要将方程两边乘以一个-1即可。
仔细看会发现所有不等式都是包含等于的,因为线性规划求出最优值并不一定是整数,所以将小于看成小于等于区别不大。
附单纯型算法代码:
#include
#define eps 1e-3
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 1005;
/*
0:有最优解
1:无界解
2:无解
m1:小于不等式个数
m2:等于等式个数
m3:大于不等式个数
n1:变量和松弛变量的个数
n2:变量、松弛变量、人工变量的个数
*/
class LinearProgram
{
public :
int n, m, m1, m2, m3, n1, n2;
int basic[maxn], nonbasic[maxn];
double a[maxn][maxn];
void init ( )
{
n1 = n+m3;
n2 = n1+m1;
for ( int i = 0; i <= n1; i ++ )
for ( int j = 0; j <= m+1; j ++ )
a[i][j] = 0.0;
for ( int i = m1+m2+1, j = m+1; i <= m; i ++, j ++ )
{
a[i][j] = -1; //初始化松弛变量的系数
a[m+1][j] = -1;
}
for ( int i = 1; i <= n1; i ++ )
nonbasic[i] = i; //非基本变量(0)
for ( int i = 1; i <= m; i ++ )
basic[i] = n1+i; //基本变量
}
void pivot ( int row, int col ) //转轴变换,将等式系数重新计算
{
for ( int j = 0; j <= n1; j ++ )
if ( j != col )
a[row][j] = a[row][j]/a[row][col];
a[row][col] = 1.0/a[row][col];
for ( int i = 0; i <= m+1; i ++ )
{
if ( i != row )
{
for ( int j = 0; j <= n1; j ++ )
{
if ( j != col )
{
a[i][j] = a[i][j]-a[i][col]*a[row][j];
if ( fabs ( a[i][j] ) < eps )
a[i][j] = 0.0;
}
}
a[i][col] = -a[i][col]*a[row][col];
}
}
swap ( basic[row], nonbasic[col] );
}
int selectCol ( int row )
{
int res = 0;
for ( int i = 1; i <= n1; i ++ )
if ( nonbasic[i] <= n2 && a[row][i] > eps )
//不在选人工变量,去掉离基变量中的人工变量,如果有解(人工变量置为0)
{
res = i;
break ; //Bland避免循环法则
}
return res;
}
int selectRow ( int col )
{
double tmp = INF;
int res = 0;
for ( int i = 1; i <= m; i ++ )
if ( a[i][col] > eps && tmp > a[i][0]/a[i][col] )
{
tmp = a[i][0]/a[i][col];
res = i;
}
return res;
}
int select ( int r )
{
for ( int col, row; ; )
{
col = selectCol ( r );
if ( col > 0 )
row = selectRow ( col );
else
return 0;
if ( row > 0 )
pivot ( row, col );
else //第col列全部是负数,则此入基变量可以无限增大
return 1; //因为离基变量将再次变正,所以无界解
}
}
int phase1 ( )
{
int res = select ( m+1 );
if ( res > 0 )
return res;
for ( int i = 1; i <= m; i ++ )
{
if ( basic[i] > n2 )
{
if ( a[i][0] > eps )
return 2;
for ( int j = 1; j <= n1; j ++ )
{
if ( fabs ( a[i][j] ) > eps )
{
pivot ( i, j );
break ;
}
}
}
}
return 0;
}
int phase2 ( )
{
return select ( 0 );
}
int compute ( )
{
if ( m != m1 )
{
int res = phase1 ( );
if ( res != 0 )
return res;
}
return phase2 ( );
}
} lp;
double ans[maxn];
void print ( )
{
memset ( ans, 0, sizeof ( ans ) );
for ( int i = 1; i <= lp.m; i ++ )
{
if ( lp.basic[i] <= lp.n )
ans[ lp.basic[i] ] = lp.a[i][0];
printf ( "%d\n", lp.basic[i] );
}
for ( int i = 1; i <= lp.n; i ++ )
printf ( "%.2lf ", ans[i] );
printf ( "\n" );
}
void solve ( )
{
char op[15];
int sign;
//freopen ( "in2.txt", "r", stdin );
while ( ~ scanf ( "%d", &lp.n ) )
{
scanf ( "%d%d%d", &lp.m1, &lp.m2, &lp.m3 );
lp.m = lp.m1+lp.m2+lp.m3;
lp.init ( );
scanf ( "%s", op );
if ( strcmp ( "max", op ) == 0 )
sign = 1;
else
sign = -1;
double x;
for ( int i = 1; i <= lp.n; i ++ )
{
scanf ( "%lf", &x );
lp.a[0][i] = x*sign;
}
scanf ( "%lf", &x );
lp.a[0][0] = x*sign;
for ( int i = 1; i <= lp.m; i ++ )
{
for ( int j = 1; j <= lp.n; j ++ )
scanf ( "%lf", &lp.a[i][j] );
scanf ( "%lf", &lp.a[i][0] );
}
for ( int j = 1; j <= lp.n; j ++ )
{
x = 0;
for ( int i = lp.m1+1; i <= lp.m; i ++ )
x += lp.a[i][j];
lp.a[lp.m+1][j] = x;
}
switch ( lp.compute ( ) )
{
case 0 :
print ( );
break ;
case 1 :
printf ( "无界解\n" );
break ;
case 2 :
printf ( "无解\n" );
}
}
}
int main ( )
{
solve ( );
return 0;
}
/*
6 0 3 0 6:变量个数 0:小于 3:等于 0:大于
max 0 -1 3 0 -2 0 0
1 3 -1 0 2 0 7 [x+3x^2-x^3+2x^4 = 7]
0 -2 4 1 0 0 12
0 -4 3 0 8 1 10
ans:0 4 5 0 0 11
4 2 1 1
max 1 1 3 -1 0
1 0 2 0 18
0 2 0 -7 0
1 1 1 1 9
0 1 -1 2 1
ans:0 3.5 4.5 1
4 3 0 0
max 0.75 -20 0.5 -6 0
0.25 -8 -1 9 0
0.5 -12 -0.5 3 0
0 0 1 0 1
ans:1 0 1 0
*/