单纯形法C++模板

单纯形法C++模板

/*
测试数据:
2 1 1
1 2
1 2 100
*****************
2 1 1
34 3
34 5 100
*****************
2 3 1
34 3
34 5 100
1 0 2
0 1 6
*/
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
const int MAXN = 51, INF = 1e9 + 10;
const double eps = 1e-8;
int N, M, opt;
int id[MAXN];
double ans[MAXN], a[MAXN][MAXN];
void Pivot(int l, int e) {
    swap(id[N + l], id[e]);
    double t = a[l][e]; a[l][e] = 1;
    for(int i = 0; i <= N; i++) a[l][i] /= t;//交换基变量与非基变量 
    for(int i = 0; i <= M; i++) {
        if(i != l && abs(a[i][e]) > eps) {
            t = a[i][e]; a[i][e] = 0;//t表示系数 
            for(int j = 0; j <= N; j++)
                a[i][j] -= a[l][j] * t;//消去需要消去的非基变量 
        }
    }//带入的过程就是消去非基变量 
}
bool init() {
    //寻找初始化解,若bi < 0,找到一个ai < 0,转换它们,不断重复直到所有的bi都 > 0
    //此时x1 = 0, x2 = 0···就是一组解 
    while(1) {
        int l = 0, e = 0;
        for(int i = 1; i <= M; i++) if(a[i][0] < -eps && (!l || (rand() & 1))) l = i;
        if(!l) break;
        for(int i = 1; i <= N; i++) if(a[l][i] < -eps && (!e || (rand() & 1))) e = i;
        if(!e) {puts("Infeasible"); return 0;}
        //这里所有的Xi都是正的,而bi是负的,这与松弛型相矛盾 
        Pivot(l, e);
    }
    return 1;
}
bool simplex() {
    while(1) {
        int l = 0, e = 0; double mn = INF;
        for(int i = 1; i <= N; i++)
            if(a[0][i] > eps) 
                {e = i; break;}
        if(!e) break;
        for(int i = 1; i <= M; i++)
            if(a[i][e] > eps && a[i][0] / a[i][e] < mn)
                mn = a[i][0] / a[i][e], l = i;//找到下界最紧的松弛 
        if(!l) {puts("Unbounded"); return 0;}
        Pivot(l, e);
    }
    return 1;
}
int main() {
    srand(19260817);
    scanf("%d",&N); scanf("%d",&M); scanf("%d",&opt);
    for(int i = 1; i <= N; i++) scanf("%lf",&a[0][i]);//最大化C1X1 + C2X2··· 
    for(int i = 1; i <= M; i++) {
        for(int j = 1; j <= N; j++)
            scanf("%lf",&a[i][j]);
        scanf("%lf",&a[i][0]);// <= b 
    }
    for(int i = 1; i <= N; i++) id[i] =  i;
    if(init() && simplex()) {
        printf("%.8lf\n", -a[0][0]);
        if(opt) {
            for(int i = 1; i <= M; i++) ans[id[i + N]] = a[i][0];//tag
            for(int i = 1; i <= N; i++) printf("%.8lf ", ans[i]);
        }
    }
    system("pause");
    return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值