线性规划单纯形模板

#include<bits/stdc++.h>
using namespace std;
const int Maxn=110,Maxm=59;
class Simplex{
    /*
       功能:
       接受有n个约束,m个基本变量的方程组a[0~n][0~m]
       a[0][]存放需要最大化的目标函数,a[][0]存放常数
       Base[]存放基本变量的id,初始为1~m
       Rest[]存放松弛变量的id,初始为m+1~m+n
       返回此线性规划的最小值ans
       要求方案的话,Base[]中的变量值为0,Rest[]中的变量值为相应行的[0]
       如果solve
       返回1,说明运行正常ans是它的最大值
       返回0,说明无可行解
       返回-1,说明解没有最大值
       测试:
       m=2,n=3
       double a[4][3]={
       {0,1,3},
       {8,-1,1},
       {-3,1,1},
       {2,1,-4}
       };
       solve=1,ans=64/3;
       注意ac不了可能是eps的问题
     */
    public:
        static const double Inf;
        static const double eps;
    int n,m;
    double a[Maxn][Maxm];
    int Base[Maxm],Rest[Maxn];
    double val[Maxm];
    double ans;
    void pt(){
        for(int i=0;i<=n;i++){
            for(int j=0;j<=m;j++)printf("%.2f ",a[i][j]);
            puts("");
        }
    }
    void pivot(int x,int y){//将第x个非基本变量和第y个基本变量调换
        swap(Rest[x],Base[y]);
        double tmp=-1./a[x][y];
        a[x][y]=-1.;
        for(int j=0;j<=m;j++)a[x][j]*=tmp;
        for(int i=0;i<=n;i++){
            if(i==x||fabs(a[i][y])<eps)continue;
            tmp=a[i][y];
            a[i][y]=0;
            for(int j=0;j<=m;j++)a[i][j]+=tmp*a[x][j];
        }
    }
    bool opt(){
        while(1){
            int csi=0;
            for(int i=1;i<=m;i++)if(a[0][i]>eps&&(!csi||Base[i]<Base[csi]))csi=i;
            if(!csi)break;
            int csj=0;
            double cur;
            for(int j=1;j<=n;j++){
                if(a[j][csi]>-eps)continue;
                double tmp=-a[j][0]/a[j][csi];
                if(!csj||tmp+eps<cur||(fabs(tmp-cur)<eps&&Rest[j]<Rest[csj]))csj=j,cur=tmp;
            }
            if(!csj)return 0;
            pivot(csj,csi);
        }
        ans=a[0][0];
        return 1;
    }
    bool init(){
        ans=0;
        for(int i=1;i<=m;i++)Base[i]=i;
        for(int i=1;i<=n;i++)Rest[i]=m+i;
        int cs=1;
        for(int i=2;i<=n;i++)if(a[i][0]<a[cs][0])cs=i;
        if(a[cs][0]>=-eps)return 1;
        static double tmp[Maxm];
        for(int i=0;i<=m;i++)tmp[i]=a[0][i],a[0][i]=0;
        for(int i=1;i<=n;i++)a[i][m+1]=1.;
        a[0][m+1]=-1.;Base[m+1]=m+n+1;
        pivot(cs,++m);
        opt();
        m--;
        if(a[0][0]<-eps)return 0;
        cs=-1;
        for(int i=1;i<=n;i++){
            if(Rest[i]>m+n){
                cs=i;
                break;
            }
        }
        if(cs>=1){
            int nxt=-1;
            m++;
            for(int i=1;i<=m;i++)if(a[cs][i]>eps||a[cs][i]<-eps){nxt=i;break;}
            pivot(cs,nxt);
            m--;
        }
        for(int i=1;i<=m;i++){
            if(Base[i]>m+n){
                swap(Base[i],Base[m+1]);
                for(int j=0;j<=n;j++)a[j][i]=a[j][m+1];
                break;
            }
        }
        for(int i=1;i<=m;i++)a[0][i]=0;a[0][0]=tmp[0];
        for(int i=1;i<=m;i++)if(Base[i]<=m)a[0][i]=tmp[Base[i]];
        for(int i=1;i<=n;i++){
            if(Rest[i]<=m){
                for(int j=0;j<=m;j++)a[0][j]+=tmp[Rest[i]]*a[i][j];
            }
        }
        return 1;
    }
    void getval(){
        for(int i=1;i<=m;i++)val[i]=0;
        for(int i=1;i<=n;i++)if(Rest[i]<=m)val[Rest[i]]=a[i][0];
        //for(int i=1;i<=m;i++)printf("%.2f ",val[i]);puts("");
    }
    int solve(){
        if(!init())return 0;
        if(!opt())return -1;
        getval();
        return 1;
    }
}solver;
const double Simplex:: Inf=1e80;
const double Simplex:: eps=1e-8;
int main(){
    int m,n,type;
    scanf("%d%d%d",&m,&n,&type);
    solver.a[0][0]=0;
    for(int i=1;i<=m;i++)scanf("%lf",&solver.a[0][i]);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m+1;j++){
            if(j==m+1)scanf("%lf",&solver.a[i][0]);
            else {
                scanf("%lf",&solver.a[i][j]);
                solver.a[i][j]=-solver.a[i][j];
            }
        }
    }
    solver.m=m,solver.n=n;
    int rep=solver.solve();
    if(rep==0)puts("Infeasible");
    else if(rep==-1)puts("Unbounded");
    else {
        printf("%.12f\n",solver.ans);
        if(type==1){
            for(int i=1;i<=m;i++)printf("%.12f%c",solver.val[i],i==m?'\n':' ');
        }
    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值