码迷,mamicode.com
首页 > 其他好文 > 详细

UOJ179 - 线性规划

时间:2018-03-17 23:24:01      阅读:295      评论:0      收藏:0      [点我收藏+]

标签:pivot   分代   span   ++   swap   指定   sim   cti   equal   

Portal

Description

求解一个标准型线性规划:
\(n\)个实数变量\(x_1,x_2,...,x_n\)\(m\)条约束,其中第\(i\)条约束形如 \(\sum_{j=1}^na_{ij}x_j\leq b_i\)
此外这\(n\)个变量需要满足非负性限制,即\(x_j≥0\)
在满足上述所有条件的情况下,你需要指定每个变量\(x_j\)的取值,使得目标函数 \(F=\sum_{j=1}^nc_jx_j\)的值最大。
其中\(1≤n,m≤20, 0≤|a_{ij}|,|b_i|,|c_j|≤100\)

Solution

线性规划模板题,用单纯形可解。墙裂推荐看看这篇论文:2 Solving LPs: The Simplex Algorithm of George Dantzig

Code

//线性规划
#include <cstdio>
#include <algorithm>
using namespace std;
inline int read()
{ 
    int x=0,f=1; char ch=getchar();
    while(ch<‘0‘||‘9‘<ch) f=(ch^‘-‘)?f:-1,ch=getchar();
    while(‘0‘<=ch&&ch<=‘9‘) x=x*10+ch-‘0‘,ch=getchar();
    return x*f;
}
int const N=30;
double const EPS=1e-8;
bool equal0(double x) {return -EPS<x&&x<EPS;}
int n,m,T;
double a[N][N];
int b[N],id[N<<1];
void pivot(int x,int y)
{
    swap(id[n+x],id[y]);
    double t=a[x][y]; a[x][y]=1;
    for(int i=0;i<=n;i++) a[x][i]/=t;
    for(int i=0;i<=m;i++)
    {
        if(i==x||equal0(a[i][y])) continue;
        t=a[i][y],a[i][y]=0;
        for(int j=0;j<=n;j++) a[i][j]-=a[x][j]*t;
    }
}
bool simplex()
{
    while(true)
    {
        int x=0,y=0;
        for(int j=1;!y&&j<=n;j++) if(a[0][j]>EPS) y=j;
        if(!y) return true;
        double minX=1e18;
        for(int i=1;i<=m;i++)
            if(a[i][y]>EPS&&minX>a[i][0]/a[i][y]) minX=a[i][0]/a[i][y],x=i;
        if(!x) {puts("Unbounded"); return false;}
        pivot(x,y);
    }
}
bool solve()
{
    for(int i=1;i<=n;i++) id[i]=i;
    while(true)
    {
        int x=0,y=0;
        for(int i=1;i<=m;i++) if(a[i][0]<-EPS&&(!x||rand()&1)) x=i;
        if(!x) return simplex();
        for(int j=1;j<=n;j++) if(a[x][j]<-EPS&&(!y||rand()&1)) y=j;
        if(!y) {puts("Infeasible"); return false;}
        pivot(x,y);
    }
}
double ans[N];
int main()
{
    n=read(),m=read(),T=read();
    for(int i=1;i<=n;i++) a[0][i]=read();
    for(int i=1;i<=m;i++)
    {
        for(int j=1;j<=n;j++) a[i][j]=read();
        a[i][0]=read();
    }
    if(solve())
    {
        printf("%.10lf\n",-a[0][0]);
        if(!T) return 0;
        for(int i=1;i<=m;i++) ans[id[n+i]]=a[i][0];
        for(int i=1;i<=n;i++) printf("%.10lf ",ans[i]);
    }
    return 0;
}

P.S.

学了一整天,弃疗背板子,然后被这篇论文拯救!
不知道uoj有什么神数据,满分代码我都看不懂...不过这个做别的线性规划都不会出锅哒。

UOJ179 - 线性规划

标签:pivot   分代   span   ++   swap   指定   sim   cti   equal   

原文地址:https://www.cnblogs.com/VisJiao/p/uoj179.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!