UOJ#179. 线性规划(单纯形)

传送门

题解:
虽然标程挂了,不过还是勉强能用的。

初始条件:

max j c j a j j a i , j x j b j x i 0

最优化过程:
假设一开始满足所有 b j 0
1.找到 c i 为正数的 x i
2.找到 b j x j , i 最小的 j
3.pivot(j,i)。

初始解:
1.找到任意 b j < 0 j .
2.找到任意 a j , i 0 i .
3.pivot(j,i).

无解条件:
init失败,即 b j < 0 且不存在 i .

无限解条件:
任意时刻基变量没有限制

pivot操作:
b i j a i , j x j x n + i = a i , e x e
x e = b i j a i , j x j x n + i a i , e

对于其他行矩阵减法即可。

#include <bits/stdc++.h>
using namespace std;
typedef long double LD;
const int N=26;
int n,m,type,q[N],id[N*2];
double a[N][N],ans[N];

namespace LP {
    const double eps=1e-8, INF=1e15;
    inline void pivot(int l,int e) {
        swap(id[l+n],id[e]);
        double t=a[l][e]; a[l][e]=1;
        for(int i=0;i<=n;i++) a[l][i]/=t;
        int p=0;
        for(int i=0;i<=n;i++) if(fabs(a[l][i])>eps) q[++p]=i;
        for(int i=0;i<=m;i++) if(i!=l && fabs(a[i][e])>eps) {
            double t=a[i][e]; a[i][e]=0;
            for(int j=1;j<=p;j++) a[i][q[j]]-=t*a[l][q[j]];
        }
    }
    inline bool init() {
        while(true) {
            int l=0,e=0;
            for(int i=1;i<=m;i++)
                if(a[i][0]<-eps && (!l || (rand()%2))) l=i;
            if(!l) break;
            for(int j=1;j<=n;j++)
                if(a[l][j]<-eps && (!e || (rand()%2))) e=j;
            if(!e) return puts("Infeasible"), false;
            pivot(l,e);
        } return true;
    }
    inline bool simplex() {
        while(true) {
            int l=0,e=0; double mn=INF;
            for(int j=1;j<=n;j++)
                if(a[0][j]>eps) {e=j; break;}
            if(!e) break;
            for(int i=1;i<=m;i++)
                if(a[i][e]>eps && mn>a[i][0]/a[i][e])
                    mn=a[i][0]/a[i][e], l=i;
            if(!l) return puts("Unbounded"), false;
            pivot(l,e);
        } return true;
    }
    inline void solve() {
        for(int i=1;i<=n;i++) id[i]=i;
        if(init() && simplex()) {
            printf("%.8lf\n",-a[0][0]);
            for(int i=1;i<=m;i++) ans[id[n+i]]=a[i][0];
            if(type) for(int i=1;i<=n;i++) printf("%.8lf ",ans[i]);
        }
    }   
}

int main() {
    cin>>n>>m>>type;
    for(int i=1;i<=n;i++) cin>>a[0][i];
    for(int i=1;i<=m;i++) {
        for(int j=1;j<=n;j++) cin>>a[i][j];
        cin>>a[i][0];
    } LP::solve();
}

猜你喜欢

转载自blog.csdn.net/qq_35649707/article/details/80962737