线性规划--单纯形法

线性规划是求一个线性多项式的最值。
线性规划有两种形式:

1.标准型 不等式型
2.松弛型 除了非负约束,其他都是等式

变量名称:

在res=x+y+z中。
1.基本变量,基本变量是res。
2.非基本变量,如x,y,z。

单纯形法:

适用于松弛型。
单纯形法是不断通过迭代来增大最大值。达到无法更新时,就是最大值。

这就是实现的简单的过程。
然而细节又很多(算法导论上有详细的描述),这里只是简单的概述。

1.没有非负约束。
    对于任意一个x没有非负约束。
    则我们将x拆成y-z,y>=0,z>=0。
2.标准型转为松弛型。
    我们假设x>=z,
    那么我们可以假设一个res=x-z,res>=0。来进行替换。

这是两个最常见的问题。
现在,我们来谈一谈迭代背后的主要思想。
每一轮迭代,我们从目标函数中找到非负的那一个变量。
然后将任意一个方程式进行替换。将一个基本变量与一个非基本变量进行交换。
然后将它带入每一个方程式(包括目标式)中进行替换原来的基本变量。
这样会增大目标值(算法导论上有证明)。
这就是主要的思想。
uoj–线性规划

#include<cstdio>
#include<iostream>
#define For(aa,bb,cc) for(int aa=(bb);aa<=(int)(cc);++aa)
using namespace std;
const double eps=1e-8,inf=1e18;
const int maxn=21;
int n,m,t,flag;
double ans[maxn],a[maxn][maxn];
int id[maxn+maxn];

template<class T>
void read(T &x){
    x=0;char c=getchar();int fuhao=1;
    while(!isdigit(c)) fuhao=c=='-'?-1:fuhao,c=getchar();
    while(isdigit(c)) x=(x<<1)+(x<<3)+(c^48),c=getchar();
    x*=fuhao;
}

inline void pivot(int line,int col){
    swap(id[col],id[n+line]);
    double res=a[line][col];
    a[line][col]=1;
    For(i,0,n) a[line][i]/=res;
    For(i,0,m){
        if(i!=line){
            res=a[i][col],a[i][col]=0;
            For(j,0,n) a[i][j]-=res*a[line][j];
        }
    }
}

inline void init_simplex(){
    int line,col;double res;
    while(1){
        line=col=0;res=-eps;
        For(i,1,m)
            if(a[i][0]<res)
                line=i,res=a[i][0];
        if(!line) break;
        For(i,1,n)
            if(a[line][i]<-eps) col=i;
        if(!col){
            puts("Infeasible");
            flag=0;
            return ;
        }
        pivot(line,col);
    }
}

inline void simplex(){
    int line,col;double res;
    while(1){
        line=col=0;
        For(i,1,n)
            if(a[0][i]>eps){
                col=i;
                break;
            }
        if(!col) break;
        res=inf;
        For(i,1,m)
            if(a[i][col]>eps && a[i][0]/a[i][col]<res) 
                res=a[i][0]/a[i][col],line=i;
        if(!line){
            puts("Unbounded");
            flag=0;
            return ;
        }
        pivot(line,col);
    }
}

int main(){
#ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
#endif
    read(n),read(m),read(t);flag=1;
    For(i,1,n) scanf("%lf",&a[0][i]),id[i]=i;//c[i]
    For(i,1,m){
        For(j,1,n) scanf("%lf",&a[i][j]);
        scanf("%lf",&a[i][0]);//b[i]
    }
    init_simplex();
    if(!flag) return 0;
    simplex();
    if(!flag) return 0;
    printf("%.10f\n",-a[0][0]);
    if(!t) return 0;
    For(i,1,m) ans[id[i+n]]=a[i][0];
    For(i,1,n) printf("%.10f ",ans[i]);
    puts("");
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值